Compare commits
10 commits
8b1417f8d7
...
9aa40ec69c
Author | SHA1 | Date | |
---|---|---|---|
|
9aa40ec69c | ||
|
5efc4d9922 | ||
|
2707331ca6 | ||
|
0e3af1bd47 | ||
|
6405af06fe | ||
|
8c3be33acb | ||
|
391f1c85d8 | ||
|
74f8c5830f | ||
|
72a8413e7b | ||
|
70ee692e20 |
21 changed files with 948 additions and 349 deletions
137
.clang-format
Normal file
137
.clang-format
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignAfterOpenBracket: Align
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: DontAlign
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: All
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: MultiLine
|
||||||
|
BinPackArguments: true
|
||||||
|
BinPackParameters: true
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
AfterExternBlock: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeColon
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros:
|
||||||
|
- foreach
|
||||||
|
- Q_FOREACH
|
||||||
|
- BOOST_FOREACH
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<ext/.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 2000
|
||||||
|
PointerAlignment: Right
|
||||||
|
RawStringFormats:
|
||||||
|
- Language: Cpp
|
||||||
|
Delimiters:
|
||||||
|
- cc
|
||||||
|
- CC
|
||||||
|
- cpp
|
||||||
|
- Cpp
|
||||||
|
- CPP
|
||||||
|
- 'c++'
|
||||||
|
- 'C++'
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
- Language: TextProto
|
||||||
|
Delimiters:
|
||||||
|
- pb
|
||||||
|
- PB
|
||||||
|
- proto
|
||||||
|
- PROTO
|
||||||
|
EnclosingFunctions:
|
||||||
|
- EqualsProto
|
||||||
|
- EquivToProto
|
||||||
|
- PARSE_PARTIAL_TEXT_PROTO
|
||||||
|
- PARSE_TEST_PROTO
|
||||||
|
- PARSE_TEXT_PROTO
|
||||||
|
- ParseTextOrDie
|
||||||
|
- ParseTextProtoOrDie
|
||||||
|
CanonicalDelimiter: ''
|
||||||
|
BasedOnStyle: google
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: false
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Auto
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
160
.clang-tidy
Normal file
160
.clang-tidy
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
---
|
||||||
|
Checks: >-
|
||||||
|
*,
|
||||||
|
-abseil-*,
|
||||||
|
-altera-*,
|
||||||
|
-android-*,
|
||||||
|
-boost-*,
|
||||||
|
-bugprone-narrowing-conversions,
|
||||||
|
-bugprone-signed-char-misuse,
|
||||||
|
-cert-dcl50-cpp,
|
||||||
|
-cert-err58-cpp,
|
||||||
|
-cert-oop57-cpp,
|
||||||
|
-cert-str34-c,
|
||||||
|
-clang-analyzer-optin.cplusplus.UninitializedObject,
|
||||||
|
-clang-analyzer-osx.*,
|
||||||
|
-clang-diagnostic-delete-abstract-non-virtual-dtor,
|
||||||
|
-clang-diagnostic-delete-non-abstract-non-virtual-dtor,
|
||||||
|
-clang-diagnostic-shadow-field,
|
||||||
|
-clang-diagnostic-unused-const-variable,
|
||||||
|
-clang-diagnostic-unused-parameter,
|
||||||
|
-concurrency-*,
|
||||||
|
-cppcoreguidelines-avoid-c-arrays,
|
||||||
|
-cppcoreguidelines-avoid-magic-numbers,
|
||||||
|
-cppcoreguidelines-init-variables,
|
||||||
|
-cppcoreguidelines-macro-usage,
|
||||||
|
-cppcoreguidelines-narrowing-conversions,
|
||||||
|
-cppcoreguidelines-non-private-member-variables-in-classes,
|
||||||
|
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
|
||||||
|
-cppcoreguidelines-pro-bounds-constant-array-index,
|
||||||
|
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
|
||||||
|
-cppcoreguidelines-pro-type-const-cast,
|
||||||
|
-cppcoreguidelines-pro-type-cstyle-cast,
|
||||||
|
-cppcoreguidelines-pro-type-member-init,
|
||||||
|
-cppcoreguidelines-pro-type-reinterpret-cast,
|
||||||
|
-cppcoreguidelines-pro-type-static-cast-downcast,
|
||||||
|
-cppcoreguidelines-pro-type-union-access,
|
||||||
|
-cppcoreguidelines-pro-type-vararg,
|
||||||
|
-cppcoreguidelines-special-member-functions,
|
||||||
|
-fuchsia-multiple-inheritance,
|
||||||
|
-fuchsia-overloaded-operator,
|
||||||
|
-fuchsia-statically-constructed-objects,
|
||||||
|
-fuchsia-default-arguments-declarations,
|
||||||
|
-fuchsia-default-arguments-calls,
|
||||||
|
-google-build-using-namespace,
|
||||||
|
-google-explicit-constructor,
|
||||||
|
-google-readability-braces-around-statements,
|
||||||
|
-google-readability-casting,
|
||||||
|
-google-readability-namespace-comments,
|
||||||
|
-google-readability-todo,
|
||||||
|
-google-runtime-references,
|
||||||
|
-hicpp-*,
|
||||||
|
-llvm-else-after-return,
|
||||||
|
-llvm-header-guard,
|
||||||
|
-llvm-include-order,
|
||||||
|
-llvm-qualified-auto,
|
||||||
|
-llvmlibc-*,
|
||||||
|
-misc-non-private-member-variables-in-classes,
|
||||||
|
-misc-no-recursion,
|
||||||
|
-misc-unused-parameters,
|
||||||
|
-modernize-avoid-c-arrays,
|
||||||
|
-modernize-avoid-bind,
|
||||||
|
-modernize-concat-nested-namespaces,
|
||||||
|
-modernize-return-braced-init-list,
|
||||||
|
-modernize-use-auto,
|
||||||
|
-modernize-use-default-member-init,
|
||||||
|
-modernize-use-equals-default,
|
||||||
|
-modernize-use-trailing-return-type,
|
||||||
|
-modernize-use-nodiscard,
|
||||||
|
-mpi-*,
|
||||||
|
-objc-*,
|
||||||
|
-readability-convert-member-functions-to-static,
|
||||||
|
-readability-else-after-return,
|
||||||
|
-readability-function-cognitive-complexity,
|
||||||
|
-readability-implicit-bool-conversion,
|
||||||
|
-readability-isolate-declaration,
|
||||||
|
-readability-magic-numbers,
|
||||||
|
-readability-make-member-function-const,
|
||||||
|
-readability-redundant-string-init,
|
||||||
|
-readability-uppercase-literal-suffix,
|
||||||
|
-readability-use-anyofallof,
|
||||||
|
WarningsAsErrors: '*'
|
||||||
|
AnalyzeTemporaryDtors: false
|
||||||
|
FormatStyle: google
|
||||||
|
CheckOptions:
|
||||||
|
- key: google-readability-braces-around-statements.ShortStatementLines
|
||||||
|
value: '1'
|
||||||
|
- key: google-readability-function-size.StatementThreshold
|
||||||
|
value: '800'
|
||||||
|
- key: google-runtime-int.TypeSuffix
|
||||||
|
value: '_t'
|
||||||
|
- key: llvm-namespace-comment.ShortNamespaceLines
|
||||||
|
value: '10'
|
||||||
|
- key: llvm-namespace-comment.SpacesBeforeComments
|
||||||
|
value: '2'
|
||||||
|
- key: modernize-loop-convert.MaxCopySize
|
||||||
|
value: '16'
|
||||||
|
- key: modernize-loop-convert.MinConfidence
|
||||||
|
value: reasonable
|
||||||
|
- key: modernize-loop-convert.NamingStyle
|
||||||
|
value: CamelCase
|
||||||
|
- key: modernize-pass-by-value.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-replace-auto-ptr.IncludeStyle
|
||||||
|
value: llvm
|
||||||
|
- key: modernize-use-nullptr.NullMacros
|
||||||
|
value: 'NULL'
|
||||||
|
- key: modernize-make-unique.MakeSmartPtrFunction
|
||||||
|
value: 'make_unique'
|
||||||
|
- key: modernize-make-unique.MakeSmartPtrFunctionHeader
|
||||||
|
value: 'esphome/core/helpers.h'
|
||||||
|
- key: readability-braces-around-statements.ShortStatementLines
|
||||||
|
value: 2
|
||||||
|
- key: readability-identifier-naming.LocalVariableCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ClassCase
|
||||||
|
value: 'CamelCase'
|
||||||
|
- key: readability-identifier-naming.StructCase
|
||||||
|
value: 'CamelCase'
|
||||||
|
- key: readability-identifier-naming.EnumCase
|
||||||
|
value: 'CamelCase'
|
||||||
|
- key: readability-identifier-naming.EnumConstantCase
|
||||||
|
value: 'UPPER_CASE'
|
||||||
|
- key: readability-identifier-naming.StaticConstantCase
|
||||||
|
value: 'UPPER_CASE'
|
||||||
|
- key: readability-identifier-naming.StaticVariableCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.GlobalConstantCase
|
||||||
|
value: 'UPPER_CASE'
|
||||||
|
- key: readability-identifier-naming.ParameterCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.PrivateMemberCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.PrivateMemberSuffix
|
||||||
|
value: '_'
|
||||||
|
- key: readability-identifier-naming.PrivateMethodCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.PrivateMethodSuffix
|
||||||
|
value: '_'
|
||||||
|
- key: readability-identifier-naming.ClassMemberCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ClassMemberCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ProtectedMemberCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ProtectedMemberSuffix
|
||||||
|
value: '_'
|
||||||
|
- key: readability-identifier-naming.FunctionCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ClassMethodCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ProtectedMethodCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.ProtectedMethodSuffix
|
||||||
|
value: '_'
|
||||||
|
- key: readability-identifier-naming.VirtualMethodCase
|
||||||
|
value: 'lower_case'
|
||||||
|
- key: readability-identifier-naming.VirtualMethodSuffix
|
||||||
|
value: ''
|
||||||
|
- key: readability-qualified-auto.AddConstToQualified
|
||||||
|
value: 0
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,3 +8,5 @@
|
||||||
living_room_screen.yaml
|
living_room_screen.yaml
|
||||||
fonts
|
fonts
|
||||||
__pycache__
|
__pycache__
|
||||||
|
mlhx/
|
||||||
|
v1/
|
||||||
|
|
|
@ -2,9 +2,9 @@ esphome:
|
||||||
name: ${device_id}
|
name: ${device_id}
|
||||||
name_add_mac_suffix: true
|
name_add_mac_suffix: true
|
||||||
on_boot:
|
on_boot:
|
||||||
- priority: 750.0
|
- priority: 220.0
|
||||||
then:
|
then:
|
||||||
- IT8951E.clear
|
- it8951e.clear
|
||||||
- delay: 100ms
|
- delay: 100ms
|
||||||
- component.update: m5paper_display
|
- component.update: m5paper_display
|
||||||
- priority: -100.0
|
- priority: -100.0
|
||||||
|
@ -13,13 +13,16 @@ esphome:
|
||||||
- component.update: m5paper_display
|
- component.update: m5paper_display
|
||||||
|
|
||||||
esp32:
|
esp32:
|
||||||
board: esp32dev
|
board: m5stack-grey
|
||||||
framework:
|
framework:
|
||||||
type: arduino
|
type: arduino
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source: github://Passific/m5paper_esphome
|
||||||
|
|
||||||
# Enable logging
|
# Enable logging
|
||||||
logger:
|
logger:
|
||||||
level: VERBOSE
|
level: DEBUG
|
||||||
|
|
||||||
# Enable psram
|
# Enable psram
|
||||||
psram:
|
psram:
|
||||||
|
@ -175,8 +178,9 @@ i2c:
|
||||||
display:
|
display:
|
||||||
- platform: it8951e
|
- platform: it8951e
|
||||||
id: m5paper_display
|
id: m5paper_display
|
||||||
display_cs_pin: GPIO15
|
cs_pin: GPIO15
|
||||||
reset_pin: GPIO23
|
reset_pin: GPIO23
|
||||||
|
reset_duration: 100ms
|
||||||
busy_pin: GPIO27
|
busy_pin: GPIO27
|
||||||
rotation: 0
|
rotation: 0
|
||||||
reversed: False
|
reversed: False
|
||||||
|
@ -492,7 +496,8 @@ switch:
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
id: ha_time
|
id: homeassistant_time
|
||||||
|
timezone: Europe/Paris
|
||||||
on_time_sync:
|
on_time_sync:
|
||||||
- bm8563.write_time
|
- bm8563.write_time
|
||||||
- platform: bm8563
|
- platform: bm8563
|
||||||
|
@ -506,14 +511,17 @@ time:
|
||||||
m5paper:
|
m5paper:
|
||||||
battery_power_pin: GPIO5
|
battery_power_pin: GPIO5
|
||||||
main_power_pin: GPIO2
|
main_power_pin: GPIO2
|
||||||
update_interval: 10s
|
|
||||||
battery_voltage:
|
|
||||||
name: ${device_name} battery voltage
|
|
||||||
id: m5paper_battery_voltage
|
|
||||||
device_class: "voltage"
|
|
||||||
state_class: "measurement"
|
|
||||||
|
|
||||||
sensor:
|
sensor:
|
||||||
|
- platform: adc
|
||||||
|
disabled_by_default: true
|
||||||
|
pin: GPIO35
|
||||||
|
name: ${device_name} battery voltage
|
||||||
|
id: m5paper_battery_voltage
|
||||||
|
update_interval: 10s
|
||||||
|
attenuation: 11db
|
||||||
|
filters:
|
||||||
|
- multiply: 2 #1,27272727
|
||||||
- platform: sht3xd
|
- platform: sht3xd
|
||||||
temperature:
|
temperature:
|
||||||
name: ${device_name} temperature
|
name: ${device_name} temperature
|
||||||
|
@ -539,13 +547,12 @@ sensor:
|
||||||
update_interval: 20s
|
update_interval: 20s
|
||||||
lambda: |-
|
lambda: |-
|
||||||
constexpr float min_level = 3.52;
|
constexpr float min_level = 3.52;
|
||||||
constexpr float max_level = 4.1;
|
constexpr float max_level = 4.15;
|
||||||
float level = ((id(m5paper_battery_voltage).state - min_level) / (max_level - min_level)) * 100.00;
|
return ((id(m5paper_battery_voltage).state - min_level) / (max_level - min_level)) * 100.00;
|
||||||
if (level < 0)
|
filters:
|
||||||
return 0;
|
- clamp:
|
||||||
if (level > 100)
|
min_value: 0
|
||||||
return 100;
|
max_value: 100
|
||||||
return level;
|
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
name: Outdoor temperature
|
name: Outdoor temperature
|
||||||
id: outdoor_temperature
|
id: outdoor_temperature
|
||||||
|
@ -563,7 +570,7 @@ sensor:
|
||||||
id: outdoor_wind_strength
|
id: outdoor_wind_strength
|
||||||
entity_id: ${outdoor_wind_strength}
|
entity_id: ${outdoor_wind_strength}
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
name: Indoor temprature
|
name: Indoor temperature
|
||||||
id: indoor_temperature
|
id: indoor_temperature
|
||||||
entity_id: ${indoor_temperature}
|
entity_id: ${indoor_temperature}
|
||||||
- platform: homeassistant
|
- platform: homeassistant
|
||||||
|
|
11
NOTES.md
Normal file
11
NOTES.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Power
|
||||||
|
|
||||||
|
PS_ON / GPIO2 enables the battery
|
||||||
|
|
||||||
|
Wake up on:
|
||||||
|
|
||||||
|
- KEY_PUSH / GPIO38 - rocker pushed in
|
||||||
|
- RTC_ALM
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# m5paper_esphome
|
# m5paper_esphome
|
||||||
|
|
||||||
Based on https://github.com/sebirdman/m5paper_esphome
|
Based on https://github.com/paveldn/m5paper_esphome
|
||||||
|
|
||||||
|
Himself based on https://github.com/sebirdman/m5paper_esphome
|
||||||
|
|
||||||
![Screen example](./img/screen_demo.jpg)
|
![Screen example](./img/screen_demo.jpg)
|
||||||
|
|
||||||
|
@ -8,7 +10,6 @@ Work in progress
|
||||||
|
|
||||||
All components are functional, but likely have bugs.
|
All components are functional, but likely have bugs.
|
||||||
|
|
||||||
Please, download font from https://materialdesignicons.com/ and put in font folder
|
Please, download font from https://materialdesignicons.com/ and put in 'fonts' folder
|
||||||
|
|
||||||
GT911 work based on: https://github.com/TomG736/esphome-GT911
|
|
||||||
BM8563 work based on: https://github.com/TomG736/esphome-BM8563
|
BM8563 work based on: https://github.com/TomG736/esphome-BM8563
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
@echo off
|
|
||||||
if [%1] == [] goto err
|
|
||||||
powershell -command "esphome compile %1 2>&1 | ? {$_.ToString().trim().Length -ne \"\" } | tee -filepath buildlog.txt"
|
|
||||||
goto:eof
|
|
||||||
:err
|
|
||||||
echo Please use with esphome configuration as parameter
|
|
||||||
echo Example: build.cmd haier.yaml
|
|
|
@ -1,7 +0,0 @@
|
||||||
@echo off
|
|
||||||
if [%1] == [] goto err
|
|
||||||
wsl --cd "%cd%" /bin/sh -c "esphome compile %1 2>&1 | tee buildlog.txt"
|
|
||||||
goto:eof
|
|
||||||
:err
|
|
||||||
echo Please use with esphome configuration as parameter
|
|
||||||
echo Example: build.cmd haier.yaml
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "esphome/core/log.h"
|
|
||||||
#include "esphome/components/i2c/i2c_bus.h"
|
|
||||||
#include "bm8563.h"
|
#include "bm8563.h"
|
||||||
|
|
||||||
|
#include "esphome/components/i2c/i2c_bus.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace bm8563 {
|
namespace bm8563 {
|
||||||
|
|
||||||
|
@ -16,13 +17,15 @@ void BM8563::update(){
|
||||||
if (!this->setupComplete) {
|
if (!this->setupComplete) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ESP_LOGI(TAG, "update");
|
||||||
this->read_time();
|
this->read_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM8563::dump_config() {
|
void BM8563::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "BM8563:");
|
ESP_LOGCONFIG(TAG, "BM8563:");
|
||||||
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
|
ESP_LOGCONFIG(TAG, " Address: 0x%02X", this->address_);
|
||||||
ESP_LOGCONFIG(TAG, " setupComplete: %s", this->setupComplete ? "true" : "false");
|
ESP_LOGCONFIG(TAG, " setupComplete: %s",
|
||||||
|
this->setupComplete ? "true" : "false");
|
||||||
if (this->sleep_duration_.has_value()) {
|
if (this->sleep_duration_.has_value()) {
|
||||||
uint32_t duration = *this->sleep_duration_;
|
uint32_t duration = *this->sleep_duration_;
|
||||||
ESP_LOGCONFIG(TAG, " Sleep Duration: %u ms", duration);
|
ESP_LOGCONFIG(TAG, " Sleep Duration: %u ms", duration);
|
||||||
|
@ -66,29 +69,28 @@ void BM8563::write_time() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM8563::read_time() {
|
void BM8563::read_time() {
|
||||||
|
ESP_LOGI(TAG, "Status2: %x %d", ReadReg(0x01), ReadReg(0x0F));
|
||||||
|
|
||||||
BM8563_TimeTypeDef BM8563_TimeStruct;
|
BM8563_TimeTypeDef BM8563_TimeStruct;
|
||||||
BM8563_DateTypeDef BM8563_DateStruct;
|
BM8563_DateTypeDef BM8563_DateStruct;
|
||||||
getTime(&BM8563_TimeStruct);
|
getTime(&BM8563_TimeStruct);
|
||||||
getDate(&BM8563_DateStruct);
|
getDate(&BM8563_DateStruct);
|
||||||
ESP_LOGD(TAG, "BM8563: %i-%i-%i %i, %i:%i:%i",
|
ESP_LOGD(TAG, "BM8563: %i-%i-%i %i, %i:%i:%i", BM8563_DateStruct.year,
|
||||||
BM8563_DateStruct.year,
|
BM8563_DateStruct.month, BM8563_DateStruct.day,
|
||||||
BM8563_DateStruct.month,
|
BM8563_DateStruct.week, BM8563_TimeStruct.hours,
|
||||||
BM8563_DateStruct.day,
|
BM8563_TimeStruct.minutes, BM8563_TimeStruct.seconds);
|
||||||
BM8563_DateStruct.week,
|
|
||||||
BM8563_TimeStruct.hours,
|
|
||||||
BM8563_TimeStruct.minutes,
|
|
||||||
BM8563_TimeStruct.seconds
|
|
||||||
);
|
|
||||||
|
|
||||||
ESPTime rtc_time{.second = uint8_t(BM8563_TimeStruct.seconds),
|
ESPTime rtc_time{
|
||||||
|
.second = uint8_t(BM8563_TimeStruct.seconds),
|
||||||
.minute = uint8_t(BM8563_TimeStruct.minutes),
|
.minute = uint8_t(BM8563_TimeStruct.minutes),
|
||||||
.hour = uint8_t(BM8563_TimeStruct.hours),
|
.hour = uint8_t(BM8563_TimeStruct.hours),
|
||||||
.day_of_week = uint8_t(BM8563_DateStruct.week),
|
.day_of_week = uint8_t(BM8563_DateStruct.week),
|
||||||
.day_of_month = uint8_t(BM8563_DateStruct.day),
|
.day_of_month = uint8_t(BM8563_DateStruct.day),
|
||||||
.day_of_year = 1, // ignored by recalc_timestamp_utc(false)
|
.day_of_year = 1, // ignored by recalc_timestamp_utc(false)
|
||||||
.month = uint8_t(BM8563_DateStruct.month),
|
.month = uint8_t(BM8563_DateStruct.month),
|
||||||
.year = uint16_t(BM8563_DateStruct.year)
|
.year = uint16_t(BM8563_DateStruct.year),
|
||||||
|
.is_dst = false, // ignored by recalc_timestamp_utc()
|
||||||
|
.timestamp = 0 // result
|
||||||
};
|
};
|
||||||
rtc_time.recalc_timestamp_utc(false);
|
rtc_time.recalc_timestamp_utc(false);
|
||||||
time::RealTimeClock::synchronize_epoch_(rtc_time.timestamp);
|
time::RealTimeClock::synchronize_epoch_(rtc_time.timestamp);
|
||||||
|
@ -130,11 +132,9 @@ void BM8563::setTime(BM8563_TimeTypeDef* BM8563_TimeStruct) {
|
||||||
if (BM8563_TimeStruct == NULL) {
|
if (BM8563_TimeStruct == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t buf[3] = {
|
uint8_t buf[3] = {byteToBcd2(BM8563_TimeStruct->seconds),
|
||||||
byteToBcd2(BM8563_TimeStruct->seconds),
|
|
||||||
byteToBcd2(BM8563_TimeStruct->minutes),
|
byteToBcd2(BM8563_TimeStruct->minutes),
|
||||||
byteToBcd2(BM8563_TimeStruct->hours)
|
byteToBcd2(BM8563_TimeStruct->hours)};
|
||||||
};
|
|
||||||
|
|
||||||
this->write_register(0x02, buf, 3);
|
this->write_register(0x02, buf, 3);
|
||||||
}
|
}
|
||||||
|
@ -167,14 +167,13 @@ void BM8563::setDate(BM8563_DateTypeDef* BM8563_DateStruct) {
|
||||||
byteToBcd2((uint8_t)(BM8563_DateStruct->year % 100)),
|
byteToBcd2((uint8_t)(BM8563_DateStruct->year % 100)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
if (BM8563_DateStruct->year < 2000) {
|
if (BM8563_DateStruct->year < 2000) {
|
||||||
buf[2] = byteToBcd2(BM8563_DateStruct->month) | 0x80;
|
buf[2] = byteToBcd2(BM8563_DateStruct->month) | 0x80;
|
||||||
} else {
|
} else {
|
||||||
buf[2] = byteToBcd2(BM8563_DateStruct->month) | 0x00;
|
buf[2] = byteToBcd2(BM8563_DateStruct->month) | 0x00;
|
||||||
}
|
}
|
||||||
|
|
||||||
ESP_LOGI(TAG, "WRiting year is %i", buf[3]);
|
ESP_LOGI(TAG, "Writing year is %i", buf[3]);
|
||||||
this->write_register(0x05, buf, 4);
|
this->write_register(0x05, buf, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +187,7 @@ uint8_t BM8563::ReadReg(uint8_t reg) {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BM8563::SetAlarmIRQ(int afterSeconds) {
|
void BM8563::SetAlarmIRQ(int afterSeconds) {
|
||||||
ESP_LOGI(TAG, "Sleep Duration: %u ms", afterSeconds);
|
ESP_LOGI(TAG, "Sleep Duration: %u ms", afterSeconds);
|
||||||
uint8_t reg_value = 0;
|
uint8_t reg_value = 0;
|
||||||
reg_value = ReadReg(0x01);
|
reg_value = ReadReg(0x01);
|
||||||
|
@ -198,26 +197,28 @@ int BM8563::SetAlarmIRQ(int afterSeconds) {
|
||||||
WriteReg(0x01, reg_value);
|
WriteReg(0x01, reg_value);
|
||||||
reg_value = 0x03;
|
reg_value = 0x03;
|
||||||
WriteReg(0x0E, reg_value);
|
WriteReg(0x0E, reg_value);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t type_value = 2;
|
uint8_t td;
|
||||||
uint8_t div = 1;
|
if (afterSeconds <= (255 * 1000 / 64)) {
|
||||||
if (afterSeconds > 255) {
|
td = 0x81;
|
||||||
div = 60;
|
afterSeconds = afterSeconds * 64 / 1000;
|
||||||
type_value = 0x83;
|
} else if (afterSeconds / 1000 <= 255) {
|
||||||
|
td = 0x82;
|
||||||
|
afterSeconds /= 1000;
|
||||||
} else {
|
} else {
|
||||||
type_value = 0x82;
|
td = 0x83;
|
||||||
|
afterSeconds /= 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
afterSeconds = (afterSeconds / div) & 0xFF;
|
WriteReg(0x0E, td);
|
||||||
WriteReg(0x0F, afterSeconds);
|
WriteReg(0x0F, std::min(afterSeconds, 0xFF));
|
||||||
WriteReg(0x0E, type_value);
|
ESP_LOGI(TAG, "%d %x", afterSeconds, td);
|
||||||
|
|
||||||
reg_value |= (1 << 0);
|
reg_value |= (1 << 0);
|
||||||
reg_value &= ~(1 << 7);
|
reg_value &= ~(1 << 7);
|
||||||
WriteReg(0x01, reg_value);
|
WriteReg(0x01, reg_value);
|
||||||
return afterSeconds * div;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM8563::clearIRQ() {
|
void BM8563::clearIRQ() {
|
||||||
|
|
|
@ -42,7 +42,7 @@ class BM8563 : public time::RealTimeClock, public i2c::I2CDevice {
|
||||||
void setTime(BM8563_TimeTypeDef* BM8563_TimeStruct);
|
void setTime(BM8563_TimeTypeDef* BM8563_TimeStruct);
|
||||||
void setDate(BM8563_DateTypeDef* BM8563_DateStruct);
|
void setDate(BM8563_DateTypeDef* BM8563_DateStruct);
|
||||||
|
|
||||||
int SetAlarmIRQ(int afterSeconds);
|
void SetAlarmIRQ(int afterSeconds);
|
||||||
int SetAlarmIRQ(const BM8563_TimeTypeDef &BM8563_TimeStruct);
|
int SetAlarmIRQ(const BM8563_TimeTypeDef &BM8563_TimeStruct);
|
||||||
int SetAlarmIRQ(const BM8563_DateTypeDef &BM8563_DateStruct, const BM8563_TimeTypeDef &BM8563_TimeStruct);
|
int SetAlarmIRQ(const BM8563_DateTypeDef &BM8563_DateStruct, const BM8563_TimeTypeDef &BM8563_TimeStruct);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
```yaml
|
```yaml
|
||||||
# example configuration:
|
# example configuration:
|
||||||
|
|
||||||
sensor:
|
|
||||||
- platform: empty_spi_sensor
|
|
||||||
name: Empty SPI sensor
|
|
||||||
cs_pin: D8
|
|
||||||
|
|
||||||
spi:
|
spi:
|
||||||
clk_pin: D5
|
clk_pin: GPIO14
|
||||||
miso_pin: D6
|
mosi_pin: GPIO12
|
||||||
|
miso_pin: GPIO13
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: it8951e
|
||||||
|
id: m5paper_display
|
||||||
|
cs_pin: GPIO15
|
||||||
|
reset_pin: GPIO23
|
||||||
|
reset_duration: 100ms
|
||||||
|
busy_pin: GPIO27
|
||||||
|
rotation: 0
|
||||||
|
reversed: False
|
||||||
|
update_interval: never
|
||||||
```
|
```
|
|
@ -12,6 +12,7 @@ from esphome.const import (
|
||||||
CONF_BUSY_PIN,
|
CONF_BUSY_PIN,
|
||||||
CONF_PAGES,
|
CONF_PAGES,
|
||||||
CONF_LAMBDA,
|
CONF_LAMBDA,
|
||||||
|
CONF_MODEL,
|
||||||
CONF_REVERSED,
|
CONF_REVERSED,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -23,6 +24,12 @@ IT8951ESensor = it8951e_ns.class_(
|
||||||
)
|
)
|
||||||
ClearAction = it8951e_ns.class_("ClearAction", automation.Action)
|
ClearAction = it8951e_ns.class_("ClearAction", automation.Action)
|
||||||
|
|
||||||
|
it8951eModel = it8951e_ns.enum("it8951eModel")
|
||||||
|
|
||||||
|
MODELS = {
|
||||||
|
"M5EPD": it8951eModel.M5EPD
|
||||||
|
}
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
CONFIG_SCHEMA = cv.All(
|
||||||
display.FULL_DISPLAY_SCHEMA.extend(
|
display.FULL_DISPLAY_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
|
@ -35,6 +42,9 @@ CONFIG_SCHEMA = cv.All(
|
||||||
cv.positive_time_period_milliseconds,
|
cv.positive_time_period_milliseconds,
|
||||||
cv.Range(max=core.TimePeriod(milliseconds=500)),
|
cv.Range(max=core.TimePeriod(milliseconds=500)),
|
||||||
),
|
),
|
||||||
|
cv.Optional(CONF_MODEL, default="M5EPD"): cv.enum(
|
||||||
|
MODELS, upper=True, space="_"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.extend(cv.polling_component_schema("1s"))
|
.extend(cv.polling_component_schema("1s"))
|
||||||
|
@ -43,7 +53,7 @@ CONFIG_SCHEMA = cv.All(
|
||||||
)
|
)
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
"IT8951E.clear",
|
"it8951e.clear",
|
||||||
ClearAction,
|
ClearAction,
|
||||||
automation.maybe_simple_id(
|
automation.maybe_simple_id(
|
||||||
{
|
{
|
||||||
|
@ -51,7 +61,7 @@ CONFIG_SCHEMA = cv.All(
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
async def bm8563_read_time_to_code(config, action_id, template_arg, args):
|
async def it8951e_clear_to_code(config, action_id, template_arg, args):
|
||||||
var = cg.new_Pvariable(action_id, template_arg)
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
await cg.register_parented(var, config[CONF_ID])
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
return var
|
return var
|
||||||
|
@ -63,6 +73,8 @@ async def to_code(config):
|
||||||
await display.register_display(var, config)
|
await display.register_display(var, config)
|
||||||
await spi.register_spi_device(var, config)
|
await spi.register_spi_device(var, config)
|
||||||
|
|
||||||
|
if CONF_MODEL in config:
|
||||||
|
cg.add(var.set_model(config[CONF_MODEL]))
|
||||||
if CONF_LAMBDA in config:
|
if CONF_LAMBDA in config:
|
||||||
lambda_ = await cg.process_lambda(
|
lambda_ = await cg.process_lambda(
|
||||||
config[CONF_LAMBDA], [(display.DisplayRef, "it")], return_type=cg.void
|
config[CONF_LAMBDA], [(display.DisplayRef, "it")], return_type=cg.void
|
||||||
|
|
|
@ -30,17 +30,6 @@ IT8951 Command defines
|
||||||
/*-----------------------------------------------------------------------
|
/*-----------------------------------------------------------------------
|
||||||
IT8951 Mode defines
|
IT8951 Mode defines
|
||||||
------------------------------------------------------------------------*/
|
------------------------------------------------------------------------*/
|
||||||
|
|
||||||
// Rotate mode
|
|
||||||
#define IT8951_ROTATE_0 0
|
|
||||||
#define IT8951_ROTATE_90 1
|
|
||||||
#define IT8951_ROTATE_180 2
|
|
||||||
#define IT8951_ROTATE_270 3
|
|
||||||
|
|
||||||
// Direction mode
|
|
||||||
#define IT8951_DIRECTION_PORTRAIT 1
|
|
||||||
#define IT8951_DIRECTION_LANDSCAPE 0
|
|
||||||
|
|
||||||
//Pixel mode (Bit per Pixel)
|
//Pixel mode (Bit per Pixel)
|
||||||
#define IT8951_2BPP 0
|
#define IT8951_2BPP 0
|
||||||
#define IT8951_3BPP 1
|
#define IT8951_3BPP 1
|
||||||
|
|
|
@ -7,12 +7,6 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace it8951e {
|
namespace it8951e {
|
||||||
|
|
||||||
//TODO: create model M5EPD
|
|
||||||
#define M5EPD_PANEL_W 960
|
|
||||||
#define M5EPD_PANEL_H 540
|
|
||||||
#define M5EPD_PANEL_ADDRL 0x36E0
|
|
||||||
#define M5EPD_PANEL_ADDRH 0x0012
|
|
||||||
|
|
||||||
static const char *TAG = "it8951e.display";
|
static const char *TAG = "it8951e.display";
|
||||||
|
|
||||||
void IT8951ESensor::write_two_byte16(uint16_t type, uint16_t cmd) {
|
void IT8951ESensor::write_two_byte16(uint16_t type, uint16_t cmd) {
|
||||||
|
@ -94,12 +88,9 @@ void IT8951ESensor::write_reg(uint16_t addr, uint16_t data) {
|
||||||
this->disable();
|
this->disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::set_target_memory_addr(uint32_t tar_addr) {
|
void IT8951ESensor::set_target_memory_addr(uint16_t tar_addrL, uint16_t tar_addrH) {
|
||||||
uint16_t h = (uint16_t)((tar_addr >> 16) & 0x0000FFFF);
|
this->write_reg(IT8951_LISAR + 2, tar_addrH);
|
||||||
uint16_t l = (uint16_t)(tar_addr & 0x0000FFFF);
|
this->write_reg(IT8951_LISAR, tar_addrL);
|
||||||
|
|
||||||
this->write_reg(IT8951_LISAR + 2, h);
|
|
||||||
this->write_reg(IT8951_LISAR, l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::write_args(uint16_t cmd, uint16_t *args, uint16_t length) {
|
void IT8951ESensor::write_args(uint16_t cmd, uint16_t *args, uint16_t length) {
|
||||||
|
@ -109,34 +100,11 @@ void IT8951ESensor::write_args(uint16_t cmd, uint16_t *args, uint16_t length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::set_rotation(uint16_t rotate) {
|
|
||||||
if (rotate < 4) {
|
|
||||||
this->m_rotate = rotate;
|
|
||||||
} else if (rotate < 90) {
|
|
||||||
this->m_rotate = IT8951_ROTATE_0;
|
|
||||||
} else if (rotate < 180) {
|
|
||||||
this->m_rotate = IT8951_ROTATE_90;
|
|
||||||
} else if (rotate < 270) {
|
|
||||||
this->m_rotate = IT8951_ROTATE_180;
|
|
||||||
} else {
|
|
||||||
this->m_rotate = IT8951_ROTATE_270;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->m_rotate == IT8951_ROTATE_0 || this->m_rotate == IT8951_ROTATE_180) {
|
|
||||||
this->m_direction = IT8951_DIRECTION_PORTRAIT;
|
|
||||||
this->device_info_.usPanelW = M5EPD_PANEL_W;
|
|
||||||
this->device_info_.usPanelH = M5EPD_PANEL_H;
|
|
||||||
} else {
|
|
||||||
this->m_direction = IT8951_DIRECTION_LANDSCAPE;
|
|
||||||
this->device_info_.usPanelW = M5EPD_PANEL_H;
|
|
||||||
this->device_info_.usPanelH = M5EPD_PANEL_W;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IT8951ESensor::set_area(uint16_t x, uint16_t y, uint16_t w,
|
void IT8951ESensor::set_area(uint16_t x, uint16_t y, uint16_t w,
|
||||||
uint16_t h) {
|
uint16_t h) {
|
||||||
uint16_t args[5];
|
uint16_t args[5];
|
||||||
args[0] = (this->m_endian_type << 8 | this->m_pix_bpp << 4 | this->m_rotate);
|
|
||||||
|
args[0] = (this->m_endian_type << 8 | this->m_pix_bpp << 4);
|
||||||
args[1] = x;
|
args[1] = x;
|
||||||
args[2] = y;
|
args[2] = y;
|
||||||
args[3] = w;
|
args[3] = w;
|
||||||
|
@ -177,8 +145,8 @@ void IT8951ESensor::check_busy(uint32_t timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::update_area(uint16_t x, uint16_t y, uint16_t w,
|
void IT8951ESensor::update_area(uint16_t x, uint16_t y, uint16_t w,
|
||||||
uint16_t h, m5epd_update_mode_t mode) {
|
uint16_t h, update_mode_e mode) {
|
||||||
if (mode == UPDATE_MODE_NONE) {
|
if (mode == update_mode_e::UPDATE_MODE_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,35 +163,14 @@ void IT8951ESensor::update_area(uint16_t x, uint16_t y, uint16_t w,
|
||||||
h = this->get_height_internal() - y;
|
h = this->get_height_internal() - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t tmp_x = x;
|
|
||||||
uint16_t tmp_y = y;
|
|
||||||
switch (this->m_rotate) {
|
|
||||||
case IT8951_ROTATE_0:
|
|
||||||
tmp_x = x;
|
|
||||||
tmp_y = y;
|
|
||||||
break;
|
|
||||||
case IT8951_ROTATE_90:
|
|
||||||
tmp_x = y;
|
|
||||||
tmp_y = M5EPD_PANEL_H - w - x;
|
|
||||||
break;
|
|
||||||
case IT8951_ROTATE_180:
|
|
||||||
tmp_x = M5EPD_PANEL_W - w - x;
|
|
||||||
tmp_y = M5EPD_PANEL_H - h - y;
|
|
||||||
break;
|
|
||||||
case IT8951_ROTATE_270:
|
|
||||||
tmp_x = M5EPD_PANEL_W - h - y;
|
|
||||||
tmp_y = x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t args[7];
|
uint16_t args[7];
|
||||||
args[0] = tmp_x;
|
args[0] = x;
|
||||||
args[1] = tmp_y;
|
args[1] = y;
|
||||||
args[2] = w;
|
args[2] = w;
|
||||||
args[3] = h;
|
args[3] = h;
|
||||||
args[4] = mode;
|
args[4] = mode;
|
||||||
args[5] = this->device_info_.usImgBufAddrL;
|
args[5] = this->IT8951DevAll[this->model_].devInfo.usImgBufAddrL;
|
||||||
args[6] = this->device_info_.usImgBufAddrH;
|
args[6] = this->IT8951DevAll[this->model_].devInfo.usImgBufAddrH;
|
||||||
|
|
||||||
this->write_args(IT8951_I80_CMD_DPY_BUF_AREA, args, 7);
|
this->write_args(IT8951_I80_CMD_DPY_BUF_AREA, args, 7);
|
||||||
}
|
}
|
||||||
|
@ -238,9 +185,9 @@ void IT8951ESensor::reset(void) {
|
||||||
|
|
||||||
uint32_t IT8951ESensor::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); }
|
uint32_t IT8951ESensor::get_buffer_length_() { return this->get_width_internal() * this->get_height_internal(); }
|
||||||
|
|
||||||
void IT8951ESensor::get_device_info(IT8951DevInfo *info) {
|
void IT8951ESensor::get_device_info(struct IT8951DevInfo_s *info) {
|
||||||
this->write_command(IT8951_I80_CMD_GET_DEV_INFO);
|
this->write_command(IT8951_I80_CMD_GET_DEV_INFO);
|
||||||
this->read_words(info, sizeof(IT8951DevInfo)/2);//Polling HRDY for each words(2-bytes) if possible
|
this->read_words(info, sizeof(struct IT8951DevInfo_s)/2); // Polling HRDY for each words(2-bytes) if possible
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t IT8951ESensor::get_vcom() {
|
uint16_t IT8951ESensor::get_vcom() {
|
||||||
|
@ -268,17 +215,8 @@ void IT8951ESensor::setup() {
|
||||||
|
|
||||||
this->busy_pin_->pin_mode(gpio::FLAG_INPUT);
|
this->busy_pin_->pin_mode(gpio::FLAG_INPUT);
|
||||||
|
|
||||||
this->get_device_info(&(this->device_info_));
|
// this->get_device_info(&(this->device_info_));
|
||||||
this->dump_config();
|
this->dump_config();
|
||||||
if (!this->device_info_.usImgBufAddrH || !this->device_info_.usImgBufAddrL) {
|
|
||||||
// Sometime it fails to read the device info
|
|
||||||
ESP_LOGE(TAG, "FAILED to read panel image buffer address, try hard...");
|
|
||||||
this->device_info_.usPanelW = M5EPD_PANEL_W;
|
|
||||||
this->device_info_.usPanelH = M5EPD_PANEL_H;
|
|
||||||
this->device_info_.usImgBufAddrL = M5EPD_PANEL_ADDRL;
|
|
||||||
this->device_info_.usImgBufAddrH = M5EPD_PANEL_ADDRH;
|
|
||||||
}
|
|
||||||
this->set_rotation(IT8951_ROTATE_0);
|
|
||||||
|
|
||||||
this->write_command(IT8951_TCON_SYS_RUN);
|
this->write_command(IT8951_TCON_SYS_RUN);
|
||||||
|
|
||||||
|
@ -309,19 +247,18 @@ void IT8951ESensor::setup() {
|
||||||
* @param y Update Y coordinate
|
* @param y Update Y coordinate
|
||||||
* @param w width of gram, >>> Must be a multiple of 4 <<<
|
* @param w width of gram, >>> Must be a multiple of 4 <<<
|
||||||
* @param h height of gram
|
* @param h height of gram
|
||||||
* @param gram 4bpp garm data
|
* @param gram 4bpp gram data
|
||||||
* @retval m5epd_err_t
|
|
||||||
*/
|
*/
|
||||||
void IT8951ESensor::write_buffer_to_display(uint16_t x, uint16_t y, uint16_t w,
|
void IT8951ESensor::write_buffer_to_display(uint16_t x, uint16_t y, uint16_t w,
|
||||||
uint16_t h, const uint8_t *gram) {
|
uint16_t h, const uint8_t *gram) {
|
||||||
this->m_endian_type = IT8951_LDIMG_B_ENDIAN;
|
this->m_endian_type = IT8951_LDIMG_B_ENDIAN;
|
||||||
this->m_pix_bpp = IT8951_4BPP;
|
this->m_pix_bpp = IT8951_4BPP;
|
||||||
if (x > this->get_width_internal() || y > this->get_height_internal()) {
|
if (x > this->get_width() || y > this->get_height()) {
|
||||||
ESP_LOGE(TAG, "Pos (%d, %d) out of bounds.", x, y);
|
ESP_LOGE(TAG, "Pos (%d, %d) out of bounds.", x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->set_target_memory_addr(this->device_info_.usImgBufAddrL | (this->device_info_.usImgBufAddrH << 16));
|
this->set_target_memory_addr(this->IT8951DevAll[this->model_].devInfo.usImgBufAddrL, this->IT8951DevAll[this->model_].devInfo.usImgBufAddrH);
|
||||||
this->set_area(x, y, w, h);
|
this->set_area(x, y, w, h);
|
||||||
|
|
||||||
uint32_t pos = 0;
|
uint32_t pos = 0;
|
||||||
|
@ -344,26 +281,23 @@ void IT8951ESensor::write_buffer_to_display(uint16_t x, uint16_t y, uint16_t w,
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::write_display() {
|
void IT8951ESensor::write_display() {
|
||||||
//this->write_command(IT8951_TCON_SYS_RUN);
|
this->write_command(IT8951_TCON_SYS_RUN);
|
||||||
this->write_buffer_to_display(0, 0, this->max_x, this->max_y, this->buffer_);
|
this->write_buffer_to_display(0, 0, this->max_x, this->max_y, this->buffer_);
|
||||||
this->update_area(0, 0, this->max_x, this->max_y, UPDATE_MODE_GC16);
|
this->update_area(0, 0, this->max_x, this->max_y, update_mode_e::UPDATE_MODE_GC16);
|
||||||
//this->update_area(0, 0, this->max_x, this->max_y, UPDATE_MODE_DU4);
|
|
||||||
this->max_x = 0;
|
this->max_x = 0;
|
||||||
this->max_y = 0;
|
this->max_y = 0;
|
||||||
//this->write_command(IT8951_TCON_SLEEP);
|
this->write_command(IT8951_TCON_SLEEP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** @brief Clear graphics buffer
|
/** @brief Clear graphics buffer
|
||||||
* @param init Screen initialization, If is 0, clear the buffer without
|
* @param init Screen initialization, If is 0, clear the buffer without initializing
|
||||||
* initializing
|
|
||||||
* @retval m5epd_err_t
|
|
||||||
*/
|
*/
|
||||||
void IT8951ESensor::clear(bool init) {
|
void IT8951ESensor::clear(bool init) {
|
||||||
this->m_endian_type = IT8951_LDIMG_L_ENDIAN;
|
this->m_endian_type = IT8951_LDIMG_L_ENDIAN;
|
||||||
this->m_pix_bpp = IT8951_4BPP;
|
this->m_pix_bpp = IT8951_4BPP;
|
||||||
|
|
||||||
this->set_target_memory_addr(this->device_info_.usImgBufAddrL | (this->device_info_.usImgBufAddrH << 16));
|
this->set_target_memory_addr(this->IT8951DevAll[this->model_].devInfo.usImgBufAddrL, this->IT8951DevAll[this->model_].devInfo.usImgBufAddrH);
|
||||||
this->set_area(0, 0, this->get_width_internal(), this->get_height_internal());
|
this->set_area(0, 0, this->get_width_internal(), this->get_height_internal());
|
||||||
uint32_t looping = (this->get_width_internal() * this->get_height_internal()) >> 2;
|
uint32_t looping = (this->get_width_internal() * this->get_height_internal()) >> 2;
|
||||||
|
|
||||||
|
@ -377,14 +311,16 @@ void IT8951ESensor::clear(bool init) {
|
||||||
this->write_command(IT8951_TCON_LD_IMG_END);
|
this->write_command(IT8951_TCON_LD_IMG_END);
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
this->update_area(0, 0, this->get_width_internal(), this->get_height_internal(), UPDATE_MODE_INIT);
|
this->update_area(0, 0, this->get_width_internal(), this->get_height_internal(), update_mode_e::UPDATE_MODE_INIT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::update() {
|
void IT8951ESensor::update() {
|
||||||
|
if (this->is_ready()) {
|
||||||
this->do_update_();
|
this->do_update_();
|
||||||
this->write_display();
|
this->write_display();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HOT IT8951ESensor::draw_absolute_pixel_internal(int x, int y, Color color) {
|
void HOT IT8951ESensor::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||||
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0) {
|
if (x >= this->get_width_internal() || y >= this->get_height_internal() || x < 0 || y < 0) {
|
||||||
|
@ -419,20 +355,27 @@ void HOT IT8951ESensor::draw_absolute_pixel_internal(int x, int y, Color color)
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT8951ESensor::get_width_internal() {
|
int IT8951ESensor::get_width_internal() {
|
||||||
return this->device_info_.usPanelW;
|
return this->IT8951DevAll[this->model_].devInfo.usPanelW;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT8951ESensor::get_height_internal() {
|
int IT8951ESensor::get_height_internal() {
|
||||||
return this->device_info_.usPanelH;
|
return this->IT8951DevAll[this->model_].devInfo.usPanelH;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT8951ESensor::dump_config() {
|
void IT8951ESensor::dump_config() {
|
||||||
ESP_LOGI(TAG, "Height:%d Width:%d LUT: %s, FW: %s, Mem:%x",
|
LOG_DISPLAY("", "IT8951E", this);
|
||||||
this->device_info_.usPanelH,
|
switch (this->model_) {
|
||||||
this->device_info_.usPanelW,
|
case it8951eModel::M5EPD:
|
||||||
this->device_info_.usLUTVersion,
|
ESP_LOGCONFIG(TAG, " Model: M5EPD");
|
||||||
this->device_info_.usFWVersion,
|
break;
|
||||||
this->device_info_.usImgBufAddrL | (this->device_info_.usImgBufAddrH << 16)
|
default:
|
||||||
|
ESP_LOGCONFIG(TAG, " Model: unkown");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_LOGCONFIG(TAG, "LUT: %s, FW: %s, Mem:%x",
|
||||||
|
this->IT8951DevAll[this->model_].devInfo.usLUTVersion,
|
||||||
|
this->IT8951DevAll[this->model_].devInfo.usFWVersion,
|
||||||
|
this->IT8951DevAll[this->model_].devInfo.usImgBufAddrL | (this->IT8951DevAll[this->model_].devInfo.usImgBufAddrH << 16)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,12 @@
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace it8951e {
|
namespace it8951e {
|
||||||
|
|
||||||
|
enum it8951eModel
|
||||||
|
{
|
||||||
|
M5EPD = 0,
|
||||||
|
it8951eModelsEND // MUST be last
|
||||||
|
};
|
||||||
|
|
||||||
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2023, 12, 0)
|
#if ESPHOME_VERSION_CODE >= VERSION_CODE(2023, 12, 0)
|
||||||
class IT8951ESensor : public display::DisplayBuffer,
|
class IT8951ESensor : public display::DisplayBuffer,
|
||||||
#else
|
#else
|
||||||
|
@ -18,7 +24,7 @@ class IT8951ESensor : public PollingComponent, public display::DisplayBuffer,
|
||||||
spi::DATA_RATE_10MHZ> {
|
spi::DATA_RATE_10MHZ> {
|
||||||
public:
|
public:
|
||||||
float get_loop_priority() const override { return 0.0f; };
|
float get_loop_priority() const override { return 0.0f; };
|
||||||
float get_setup_priority() const override { return setup_priority::HARDWARE; };
|
float get_setup_priority() const override { return setup_priority::PROCESSOR; };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
---------------------------------------- Refresh mode description
|
---------------------------------------- Refresh mode description
|
||||||
|
@ -90,49 +96,47 @@ shown in Figure 1. The use of a white image in the transition from 4-bit to
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
struct IT8951DevInfo_s
|
||||||
{
|
{
|
||||||
uint16_t usPanelW; // these are incorrect
|
uint16_t usPanelW;
|
||||||
uint16_t usPanelH; // on m5paper
|
uint16_t usPanelH;
|
||||||
uint16_t usImgBufAddrL;
|
uint16_t usImgBufAddrL;
|
||||||
uint16_t usImgBufAddrH;
|
uint16_t usImgBufAddrH;
|
||||||
char usFWVersion[16]; // empty on m5paper
|
char usFWVersion[16];
|
||||||
char usLUTVersion[16]; // empty on m5paper
|
char usLUTVersion[16];
|
||||||
}IT8951DevInfo;
|
};
|
||||||
|
|
||||||
typedef enum // Typical
|
struct IT8951Dev_s
|
||||||
|
{
|
||||||
|
struct IT8951DevInfo_s devInfo;
|
||||||
|
display::DisplayType displayType;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum update_mode_e // Typical
|
||||||
{ // Ghosting Update Time Usage
|
{ // Ghosting Update Time Usage
|
||||||
UPDATE_MODE_INIT = 0, // * N/A 2000ms Display initialization,
|
UPDATE_MODE_INIT = 0, // * N/A 2000ms Display initialization,
|
||||||
UPDATE_MODE_DU = 1, // Low 260ms Monochrome menu, text
|
UPDATE_MODE_DU = 1, // Low 260ms Monochrome menu, text input, and touch screen input
|
||||||
// input, and touch screen input
|
|
||||||
UPDATE_MODE_GC16 = 2, // * Very Low 450ms High quality images
|
UPDATE_MODE_GC16 = 2, // * Very Low 450ms High quality images
|
||||||
UPDATE_MODE_GL16 =
|
UPDATE_MODE_GL16 = 3, // * Medium 450ms Text with white background
|
||||||
3, // * Medium 450ms Text with white background
|
UPDATE_MODE_GLR16 = 4, // Low 450ms Text with white background
|
||||||
UPDATE_MODE_GLR16 =
|
UPDATE_MODE_GLD16 = 5, // Low 450ms Text and graphics with white background
|
||||||
4, // Low 450ms Text with white background
|
UPDATE_MODE_DU4 = 6, // * Medium 120ms Fast page flipping at reduced contrast
|
||||||
UPDATE_MODE_GLD16 =
|
UPDATE_MODE_A2 = 7, // Medium 290ms Anti-aliased text in menus / touch and screen input
|
||||||
5, // Low 450ms Text and graphics with white background
|
|
||||||
UPDATE_MODE_DU4 =
|
|
||||||
6, // * Medium 120ms Fast page flipping at reduced contrast
|
|
||||||
UPDATE_MODE_A2 = 7, // Medium 290ms Anti-aliased text in menus
|
|
||||||
// / touch and screen input
|
|
||||||
UPDATE_MODE_NONE = 8
|
UPDATE_MODE_NONE = 8
|
||||||
} m5epd_update_mode_t; // The ones marked with * are more commonly used
|
}; // The ones marked with * are more commonly used
|
||||||
|
|
||||||
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
|
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
|
||||||
void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
|
void set_busy_pin(GPIOPin *busy) { this->busy_pin_ = busy; }
|
||||||
|
|
||||||
void set_rotation(uint16_t rotate);
|
|
||||||
void set_reversed(bool reversed) { this->reversed_ = reversed; }
|
void set_reversed(bool reversed) { this->reversed_ = reversed; }
|
||||||
void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; }
|
void set_reset_duration(uint32_t reset_duration) { this->reset_duration_ = reset_duration; }
|
||||||
|
void set_model(it8951eModel model) { this->model_ = model; }
|
||||||
uint8_t get_rotate(void) { return m_rotate; };
|
|
||||||
uint8_t get_direction(void) { return m_direction; };
|
|
||||||
|
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_BINARY; }
|
|
||||||
|
display::DisplayType get_display_type() override { return IT8951DevAll[this->model_].displayType; }
|
||||||
|
|
||||||
void clear(bool init);
|
void clear(bool init);
|
||||||
|
|
||||||
|
@ -147,14 +151,22 @@ typedef enum // Typical
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IT8951DevInfo device_info_;
|
struct IT8951Dev_s IT8951DevAll[it8951eModel::it8951eModelsEND]
|
||||||
|
{ // it8951eModel::M5EPD
|
||||||
|
960, // .devInfo.usPanelW
|
||||||
|
540, // .devInfo.usPanelH
|
||||||
|
0x36E0, // .devInfo.usImgBufAddrL
|
||||||
|
0x0012, // .devInfo.usImgBufAddrH
|
||||||
|
"", // .devInfo.usFWVersion
|
||||||
|
"", // .devInfo.usFWVersion
|
||||||
|
display::DisplayType::DISPLAY_TYPE_GRAYSCALE // .displayType (M5EPD supports 16 gray scale levels)
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t *should_write_buffer_{nullptr};
|
uint8_t *should_write_buffer_{nullptr};
|
||||||
void get_device_info(IT8951DevInfo *info);
|
void get_device_info(struct IT8951DevInfo_s *info);
|
||||||
|
|
||||||
uint32_t max_x = 0;
|
uint32_t max_x = 0;
|
||||||
uint32_t max_y = 0;
|
uint32_t max_y = 0;
|
||||||
uint8_t m_rotate = 0;
|
|
||||||
uint8_t m_direction = 1;
|
|
||||||
uint16_t m_endian_type, m_pix_bpp;
|
uint16_t m_endian_type, m_pix_bpp;
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,6 +175,7 @@ typedef enum // Typical
|
||||||
|
|
||||||
bool reversed_ = false;
|
bool reversed_ = false;
|
||||||
uint32_t reset_duration_{100};
|
uint32_t reset_duration_{100};
|
||||||
|
enum it8951eModel model_{it8951eModel::M5EPD};
|
||||||
|
|
||||||
void reset(void);
|
void reset(void);
|
||||||
|
|
||||||
|
@ -180,12 +193,12 @@ typedef enum // Typical
|
||||||
void write_command(uint16_t cmd);
|
void write_command(uint16_t cmd);
|
||||||
void write_word(uint16_t cmd);
|
void write_word(uint16_t cmd);
|
||||||
void write_reg(uint16_t addr, uint16_t data);
|
void write_reg(uint16_t addr, uint16_t data);
|
||||||
void set_target_memory_addr(uint32_t tar_addr);
|
void set_target_memory_addr(uint16_t tar_addrL, uint16_t tar_addrH);
|
||||||
void write_args(uint16_t cmd, uint16_t *args, uint16_t length);
|
void write_args(uint16_t cmd, uint16_t *args, uint16_t length);
|
||||||
|
|
||||||
void set_area(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
void set_area(uint16_t x, uint16_t y, uint16_t w, uint16_t h);
|
||||||
void update_area(uint16_t x, uint16_t y, uint16_t w,
|
void update_area(uint16_t x, uint16_t y, uint16_t w,
|
||||||
uint16_t h, m5epd_update_mode_t mode);
|
uint16_t h, update_mode_e mode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,18 +2,13 @@ import esphome.codegen as cg
|
||||||
from esphome import pins
|
from esphome import pins
|
||||||
import esphome.config_validation as cv
|
import esphome.config_validation as cv
|
||||||
from esphome import automation
|
from esphome import automation
|
||||||
from esphome.components import sensor
|
|
||||||
from esphome.const import (
|
from esphome.const import (
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
DEVICE_CLASS_VOLTAGE,
|
|
||||||
CONF_BATTERY_VOLTAGE,
|
|
||||||
UNIT_VOLT,
|
|
||||||
STATE_CLASS_MEASUREMENT,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
m5paper_ns = cg.esphome_ns.namespace('m5paper')
|
m5paper_ns = cg.esphome_ns.namespace('m5paper')
|
||||||
|
|
||||||
M5PaperComponent = m5paper_ns.class_('M5PaperComponent', cg.PollingComponent)
|
M5PaperComponent = m5paper_ns.class_('M5PaperComponent', cg.Component)
|
||||||
PowerAction = m5paper_ns.class_("PowerAction", automation.Action)
|
PowerAction = m5paper_ns.class_("PowerAction", automation.Action)
|
||||||
|
|
||||||
CONF_MAIN_POWER_PIN = "main_power_pin"
|
CONF_MAIN_POWER_PIN = "main_power_pin"
|
||||||
|
@ -22,14 +17,8 @@ CONF_BATTERY_POWER_PIN = "battery_power_pin"
|
||||||
CONFIG_SCHEMA = cv.Schema({
|
CONFIG_SCHEMA = cv.Schema({
|
||||||
cv.GenerateID(): cv.declare_id(M5PaperComponent),
|
cv.GenerateID(): cv.declare_id(M5PaperComponent),
|
||||||
cv.Required(CONF_MAIN_POWER_PIN): pins.gpio_output_pin_schema,
|
cv.Required(CONF_MAIN_POWER_PIN): pins.gpio_output_pin_schema,
|
||||||
cv.Required(CONF_BATTERY_POWER_PIN): pins.gpio_output_pin_schema,
|
cv.Required(CONF_BATTERY_POWER_PIN): pins.gpio_output_pin_schema
|
||||||
cv.Optional(CONF_BATTERY_VOLTAGE): sensor.sensor_schema(
|
})
|
||||||
unit_of_measurement=UNIT_VOLT,
|
|
||||||
accuracy_decimals=3,
|
|
||||||
device_class=DEVICE_CLASS_VOLTAGE,
|
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
|
||||||
)
|
|
||||||
}).extend(cv.polling_component_schema('60s'))
|
|
||||||
|
|
||||||
@automation.register_action(
|
@automation.register_action(
|
||||||
"m5paper.shutdown_main_power",
|
"m5paper.shutdown_main_power",
|
||||||
|
@ -56,6 +45,3 @@ async def to_code(config):
|
||||||
if CONF_BATTERY_POWER_PIN in config:
|
if CONF_BATTERY_POWER_PIN in config:
|
||||||
power = await cg.gpio_pin_expression(config[CONF_BATTERY_POWER_PIN])
|
power = await cg.gpio_pin_expression(config[CONF_BATTERY_POWER_PIN])
|
||||||
cg.add(var.set_battery_power_pin(power))
|
cg.add(var.set_battery_power_pin(power))
|
||||||
if CONF_BATTERY_VOLTAGE in config:
|
|
||||||
sens = await sensor.new_sensor(config[CONF_BATTERY_VOLTAGE])
|
|
||||||
cg.add(var.set_battery_voltage(sens))
|
|
|
@ -1,14 +1,10 @@
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
#include "m5paper.h"
|
#include "m5paper.h"
|
||||||
#include "soc/adc_channel.h"
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace m5paper {
|
namespace m5paper {
|
||||||
|
|
||||||
#define BASE_VOLATAGE 3600
|
|
||||||
#define SCALE 0.5//0.78571429
|
|
||||||
#define ADC_FILTER_SAMPLE 16
|
|
||||||
|
|
||||||
// hack to hold power lines up in deep sleep mode
|
// hack to hold power lines up in deep sleep mode
|
||||||
// battery life isn't great with deep sleep, recommend bm8563 sleep
|
// battery life isn't great with deep sleep, recommend bm8563 sleep
|
||||||
#define ALLOW_ESPHOME_DEEP_SLEEP true
|
#define ALLOW_ESPHOME_DEEP_SLEEP true
|
||||||
|
@ -16,7 +12,7 @@ namespace m5paper {
|
||||||
static const char *TAG = "m5paper.component";
|
static const char *TAG = "m5paper.component";
|
||||||
|
|
||||||
void M5PaperComponent::setup() {
|
void M5PaperComponent::setup() {
|
||||||
ESP_LOGE(TAG, "m5paper starting up!");
|
ESP_LOGCONFIG(TAG, "m5paper starting up!");
|
||||||
this->main_power_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
this->main_power_pin_->pin_mode(gpio::FLAG_OUTPUT);
|
||||||
this->main_power_pin_->digital_write(true);
|
this->main_power_pin_->digital_write(true);
|
||||||
|
|
||||||
|
@ -27,19 +23,10 @@ void M5PaperComponent::setup() {
|
||||||
gpio_hold_en(GPIO_NUM_2);
|
gpio_hold_en(GPIO_NUM_2);
|
||||||
gpio_hold_en(GPIO_NUM_5);
|
gpio_hold_en(GPIO_NUM_5);
|
||||||
}
|
}
|
||||||
|
|
||||||
adc_power_acquire();
|
|
||||||
|
|
||||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
|
||||||
adc1_config_channel_atten(ADC1_GPIO35_CHANNEL, ADC_ATTEN_DB_11);
|
|
||||||
this->_adc_chars = (esp_adc_cal_characteristics_t *)calloc(1, sizeof(esp_adc_cal_characteristics_t));
|
|
||||||
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, BASE_VOLATAGE, this->_adc_chars);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void M5PaperComponent::shutdown_main_power() {
|
void M5PaperComponent::shutdown_main_power() {
|
||||||
ESP_LOGE(TAG, "Shutting Down Power");
|
ESP_LOGE(TAG, "Shutting Down Power");
|
||||||
adc_power_release();
|
|
||||||
|
|
||||||
if (ALLOW_ESPHOME_DEEP_SLEEP) {
|
if (ALLOW_ESPHOME_DEEP_SLEEP) {
|
||||||
gpio_hold_dis(GPIO_NUM_2);
|
gpio_hold_dis(GPIO_NUM_2);
|
||||||
gpio_hold_dis(GPIO_NUM_5);
|
gpio_hold_dis(GPIO_NUM_5);
|
||||||
|
@ -47,25 +34,8 @@ void M5PaperComponent::shutdown_main_power() {
|
||||||
this->main_power_pin_->digital_write(false);
|
this->main_power_pin_->digital_write(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void M5PaperComponent::update() {
|
|
||||||
uint32_t adc_raw_value = 0;
|
|
||||||
for (uint16_t i = 0; i < ADC_FILTER_SAMPLE; i++)
|
|
||||||
{
|
|
||||||
adc_raw_value += adc1_get_raw(ADC1_GPIO35_CHANNEL);
|
|
||||||
}
|
|
||||||
|
|
||||||
adc_raw_value = adc_raw_value / ADC_FILTER_SAMPLE;
|
|
||||||
uint32_t millivolts = (uint32_t)(esp_adc_cal_raw_to_voltage(adc_raw_value, _adc_chars) / SCALE);
|
|
||||||
|
|
||||||
float voltage = static_cast<float>(millivolts) * 0.001f;
|
|
||||||
|
|
||||||
if (this->battery_voltage_ != nullptr)
|
|
||||||
this->battery_voltage_->publish_state(voltage);
|
|
||||||
this->status_clear_warning();
|
|
||||||
}
|
|
||||||
|
|
||||||
void M5PaperComponent::dump_config() {
|
void M5PaperComponent::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "Empty custom sensor");
|
ESP_LOGCONFIG(TAG, "M5Paper");
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace m5paper
|
} //namespace m5paper
|
||||||
|
|
|
@ -1,36 +1,26 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "esphome/core/component.h"
|
#include "esphome/core/component.h"
|
||||||
#include "esphome/components/sensor/sensor.h"
|
|
||||||
#include "esphome/core/gpio.h"
|
#include "esphome/core/gpio.h"
|
||||||
#include "esphome/core/automation.h"
|
#include "esphome/core/automation.h"
|
||||||
|
|
||||||
#ifdef USE_ESP32
|
|
||||||
#include "driver/adc.h"
|
|
||||||
#include <esp_adc_cal.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace m5paper {
|
namespace m5paper {
|
||||||
|
|
||||||
class M5PaperComponent : public PollingComponent {
|
class M5PaperComponent : public Component {
|
||||||
void setup() override;
|
void setup() override;
|
||||||
void update() override;
|
|
||||||
void dump_config() override;
|
void dump_config() override;
|
||||||
float get_setup_priority() const override { return setup_priority::HARDWARE; };
|
/* Very early setup as takes care of powering other components */
|
||||||
|
float get_setup_priority() const override { return setup_priority::BUS; };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void set_battery_power_pin(GPIOPin *power) { this->battery_power_pin_ = power; }
|
void set_battery_power_pin(GPIOPin *power) { this->battery_power_pin_ = power; }
|
||||||
void set_main_power_pin(GPIOPin *power) { this->main_power_pin_ = power; }
|
void set_main_power_pin(GPIOPin *power) { this->main_power_pin_ = power; }
|
||||||
void set_battery_voltage(sensor::Sensor *battery_voltage) { battery_voltage_ = battery_voltage; }
|
|
||||||
void shutdown_main_power();
|
void shutdown_main_power();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GPIOPin *battery_power_pin_{nullptr};
|
GPIOPin *battery_power_pin_{nullptr};
|
||||||
GPIOPin *main_power_pin_{nullptr};
|
GPIOPin *main_power_pin_{nullptr};
|
||||||
sensor::Sensor *battery_voltage_{nullptr};
|
|
||||||
|
|
||||||
esp_adc_cal_characteristics_t *_adc_chars;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,6 +29,5 @@ template<typename... Ts> class PowerAction : public Action<Ts...>, public Parent
|
||||||
void play(Ts... x) override { this->parent_->shutdown_main_power(); }
|
void play(Ts... x) override { this->parent_->shutdown_main_power(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} //namespace m5paper
|
} //namespace m5paper
|
||||||
} //namespace esphome
|
} //namespace esphome
|
288
m5paper.yaml
Normal file
288
m5paper.yaml
Normal file
|
@ -0,0 +1,288 @@
|
||||||
|
esphome:
|
||||||
|
name: ${device_id}
|
||||||
|
name_add_mac_suffix: true
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
includes:
|
||||||
|
- render.h
|
||||||
|
# on_boot:
|
||||||
|
# - priority: -100.0
|
||||||
|
# then:
|
||||||
|
# - delay: ${default_update_interval}
|
||||||
|
# - component.update: m5paper_display
|
||||||
|
# - delay: 1s
|
||||||
|
# - bm8563.apply_sleep_duration
|
||||||
|
# - m5paper.shutdown_main_power
|
||||||
|
# - deep_sleep.enter:
|
||||||
|
# sleep_duration: 30s
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: m5stack-grey
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source:
|
||||||
|
type: local
|
||||||
|
path: components
|
||||||
|
|
||||||
|
logger:
|
||||||
|
level: DEBUG
|
||||||
|
baud_rate: 921600
|
||||||
|
|
||||||
|
psram:
|
||||||
|
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
power_save_mode: "HIGH"
|
||||||
|
fast_connect: true
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: material_icons_map
|
||||||
|
type: std::map<std::string, std::string>
|
||||||
|
restore_value: no
|
||||||
|
initial_value: |
|
||||||
|
{
|
||||||
|
{"mdi-weather-night", ""},
|
||||||
|
{"mdi-weather-cloudy", ""},
|
||||||
|
{"mdi-weather-cloudy-alert", ""},
|
||||||
|
{"mdi-weather-fog", ""},
|
||||||
|
{"mdi-weather-hail", ""},
|
||||||
|
{"mdi-weather-lightning-rainy", ""},
|
||||||
|
{"mdi-weather-lightning", ""},
|
||||||
|
{"mdi-weather-partly-cloudy", ""},
|
||||||
|
{"mdi-weather-night-partly-cloudy", ""},
|
||||||
|
{"mdi-weather-pouring", ""},
|
||||||
|
{"mdi-weather-rainy", ""},
|
||||||
|
{"mdi-weather-snowy-rainy", ""},
|
||||||
|
{"mdi-weather-snowy", ""},
|
||||||
|
{"mdi-weather-sunny", ""},
|
||||||
|
{"mdi-weather-windy-variant", ""},
|
||||||
|
{"mdi-weather-windy", ""},
|
||||||
|
{"mdi-cloud-question", ""},
|
||||||
|
{"mdi-thermometer", ""},
|
||||||
|
{"mdi-water-percent", ""},
|
||||||
|
{"mdi-molecule-co2", ""},
|
||||||
|
{"mdi-wind-power-outline", ""},
|
||||||
|
{"mdi-home-outline", ""},
|
||||||
|
{"mdi-tree-outline", ""},
|
||||||
|
{"mdi-gauge", ""},
|
||||||
|
{"mdi-battery-high", ""},
|
||||||
|
{"mdi-battery-medium", ""},
|
||||||
|
{"mdi-battery-low", ""},
|
||||||
|
{"mdi-battery-alert-variant-outline", ""},
|
||||||
|
{"mdi-battery-charging-high", ""},
|
||||||
|
{"mdi-battery-unknown", ""},
|
||||||
|
{"mdi-shield-outline", ""},
|
||||||
|
{"mdi-shield-home-outline", ""},
|
||||||
|
{"mdi-shield-lock-outline", ""},
|
||||||
|
{"mdi-shield-moon-outline", ""},
|
||||||
|
{"mdi-shield-alert-outline", ""},
|
||||||
|
{"mdi-molecule-co2", ""},
|
||||||
|
{"mdi-radioactive", ""},
|
||||||
|
{"mdi-numeric-0-circle-outline", ""},
|
||||||
|
{"mdi-numeric-1-circle-outline", ""},
|
||||||
|
{"mdi-numeric-2-circle-outline", ""},
|
||||||
|
{"mdi-numeric-3-circle-outline", ""},
|
||||||
|
{"mdi-numeric-4-circle-outline", ""},
|
||||||
|
{"mdi-numeric-5-circle-outline", ""},
|
||||||
|
{"mdi-numeric-6-circle-outline", ""},
|
||||||
|
{"mdi-numeric-7-circle-outline", ""},
|
||||||
|
{"mdi-numeric-8-circle-outline", ""},
|
||||||
|
{"mdi-numeric-9-plus-circle-outline", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
font:
|
||||||
|
- file: 'gfonts://Roboto'
|
||||||
|
id: normal_font
|
||||||
|
size: 120
|
||||||
|
- file: 'gfonts://Roboto'
|
||||||
|
id: small_font
|
||||||
|
size: 50
|
||||||
|
- file: 'gfonts://Roboto'
|
||||||
|
id: clock_font
|
||||||
|
size: 260
|
||||||
|
glyphs: "0123456789:"
|
||||||
|
- file: "fonts/materialdesignicons-webfont.ttf"
|
||||||
|
id: battery_font
|
||||||
|
size: 40
|
||||||
|
glyphs: [
|
||||||
|
'', #mdi-battery-medium
|
||||||
|
'', #mdi-battery-low
|
||||||
|
'', # mdi-battery-high
|
||||||
|
'', #mdi-battery-alert-variant-outline
|
||||||
|
'', #mdi-battery-charging-high
|
||||||
|
'', #mdi-battery-unknown
|
||||||
|
]
|
||||||
|
|
||||||
|
spi:
|
||||||
|
clk_pin: GPIO14
|
||||||
|
mosi_pin: GPIO12
|
||||||
|
miso_pin: GPIO13
|
||||||
|
|
||||||
|
i2c:
|
||||||
|
sda: GPIO21
|
||||||
|
scl: GPIO22
|
||||||
|
|
||||||
|
display:
|
||||||
|
- platform: it8951e
|
||||||
|
id: m5paper_display
|
||||||
|
cs_pin: GPIO15
|
||||||
|
reset_pin: GPIO23
|
||||||
|
reset_duration: 5ms
|
||||||
|
busy_pin: GPIO27
|
||||||
|
rotation: 0
|
||||||
|
reversed: False
|
||||||
|
update_interval: never
|
||||||
|
lambda: |-
|
||||||
|
render(it);
|
||||||
|
|
||||||
|
touchscreen:
|
||||||
|
- platform: gt911
|
||||||
|
display: m5paper_display
|
||||||
|
id: gt911_touchscreen
|
||||||
|
interrupt_pin: GPIO36
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: restart
|
||||||
|
id: restart_switch
|
||||||
|
name: ${device_name} restart
|
||||||
|
- platform: gpio
|
||||||
|
pin: 32
|
||||||
|
name: "led"
|
||||||
|
inverted: true
|
||||||
|
|
||||||
|
time:
|
||||||
|
- platform: homeassistant
|
||||||
|
id: homeassistant_time
|
||||||
|
on_time_sync:
|
||||||
|
- bm8563.write_time
|
||||||
|
- platform: bm8563
|
||||||
|
id: rtc_time
|
||||||
|
sleep_duration: 250s
|
||||||
|
# on_time:
|
||||||
|
# - seconds: /6
|
||||||
|
# then:
|
||||||
|
# - component.update: m5paper_display
|
||||||
|
|
||||||
|
script:
|
||||||
|
- id: suspend
|
||||||
|
then:
|
||||||
|
- component.update: m5paper_display
|
||||||
|
- delay: 2s
|
||||||
|
- bm8563.apply_sleep_duration
|
||||||
|
- m5paper.shutdown_main_power
|
||||||
|
- delay: 30s
|
||||||
|
- deep_sleep.enter:
|
||||||
|
sleep_duration: ${sleep_duration}
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 1s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
and:
|
||||||
|
# - lambda: "return !std::isnan(id(m5paper_battery_level).state);"
|
||||||
|
- lambda: "return id(rtc_time).now().is_valid();"
|
||||||
|
- lambda: "return !std::isnan(id(outside_temperature).state);"
|
||||||
|
- lambda: "return !std::isnan(id(lounge_temperature).state);"
|
||||||
|
then:
|
||||||
|
- script.execute: suspend
|
||||||
|
- interval: 3s
|
||||||
|
then:
|
||||||
|
- delay: 30s
|
||||||
|
- script.execute: suspend
|
||||||
|
|
||||||
|
m5paper:
|
||||||
|
battery_power_pin: GPIO5
|
||||||
|
main_power_pin: GPIO2
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: adc
|
||||||
|
disabled_by_default: true
|
||||||
|
pin: GPIO35
|
||||||
|
name: ${device_name} battery voltage
|
||||||
|
id: m5paper_battery_voltage
|
||||||
|
update_interval: ${default_update_interval}
|
||||||
|
attenuation: 11db
|
||||||
|
filters:
|
||||||
|
- multiply: 2 #1,27272727
|
||||||
|
- platform: sht3xd
|
||||||
|
address: 0x44
|
||||||
|
temperature:
|
||||||
|
name: ${device_name} temperature
|
||||||
|
id: m5paper_temperature
|
||||||
|
device_class: "temperature"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: mdi:thermometer
|
||||||
|
humidity:
|
||||||
|
name: ${device_name} humidity
|
||||||
|
id: m5paper_humidity
|
||||||
|
device_class: "humidity"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: mdi:water-percent
|
||||||
|
update_interval: ${default_update_interval}
|
||||||
|
- platform: template
|
||||||
|
name: ${device_name} battery level
|
||||||
|
id: m5paper_battery_level
|
||||||
|
unit_of_measurement: '%'
|
||||||
|
device_class: "battery"
|
||||||
|
state_class: "measurement"
|
||||||
|
icon: mdi:battery-high
|
||||||
|
update_interval: 20s
|
||||||
|
lambda: |-
|
||||||
|
constexpr float min_level = 3.52;
|
||||||
|
constexpr float max_level = 4.15;
|
||||||
|
return ((id(m5paper_battery_voltage).state - min_level) / (max_level - min_level)) * 100.00;
|
||||||
|
filters:
|
||||||
|
- clamp:
|
||||||
|
min_value: 0
|
||||||
|
max_value: 100
|
||||||
|
- platform: homeassistant
|
||||||
|
name: Outside temperature
|
||||||
|
id: outside_temperature
|
||||||
|
entity_id: sensor.ruuvitag_1a2d_temperature
|
||||||
|
- platform: homeassistant
|
||||||
|
name: Lounge temperature
|
||||||
|
id: lounge_temperature
|
||||||
|
entity_id: sensor.ruuvitag_963b_temperature
|
||||||
|
- platform: homeassistant
|
||||||
|
name: solar power
|
||||||
|
id: solar_power
|
||||||
|
entity_id: sensor.solax_pv1_power
|
||||||
|
- platform: uptime
|
||||||
|
id: uptime_sensor
|
||||||
|
name: Uptime
|
||||||
|
update_interval: 3s
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
name: ${device_name} right button
|
||||||
|
id: right_button
|
||||||
|
icon: mdi:gesture-tap-button
|
||||||
|
pin:
|
||||||
|
number: GPIO37
|
||||||
|
inverted: true
|
||||||
|
- platform: gpio
|
||||||
|
name: ${device_name} left button
|
||||||
|
icon: mdi:gesture-tap-button
|
||||||
|
pin:
|
||||||
|
number: GPIO39
|
||||||
|
inverted: true
|
||||||
|
- platform: gpio
|
||||||
|
name: ${device_name} BTN/PWR button
|
||||||
|
icon: mdi:gesture-tap-button
|
||||||
|
pin:
|
||||||
|
number: GPIO38
|
||||||
|
inverted: true
|
||||||
|
|
||||||
|
deep_sleep:
|
||||||
|
run_duration: 120s
|
||||||
|
sleep_duration: ${sleep_duration}
|
||||||
|
|
9
pipish.yaml
Normal file
9
pipish.yaml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
substitutions:
|
||||||
|
device_name: Pipish
|
||||||
|
device_id: pipish
|
||||||
|
project_name: juju.pipish
|
||||||
|
project_version: "0.1"
|
||||||
|
default_update_interval: "10s"
|
||||||
|
sleep_duration: 10s
|
||||||
|
|
||||||
|
<<: !include m5paper.yaml
|
88
render.h
Normal file
88
render.h
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
inline int measure_width(const char* text, esphome::display::BaseFont& font) {
|
||||||
|
int width;
|
||||||
|
int x_offset;
|
||||||
|
int baseline;
|
||||||
|
int height;
|
||||||
|
font.measure(text, &width, &x_offset, &baseline, &height);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int measure_height(const char* text, esphome::display::BaseFont& font) {
|
||||||
|
int width;
|
||||||
|
int x_offset;
|
||||||
|
int baseline;
|
||||||
|
int height;
|
||||||
|
font.measure(text, &width, &x_offset, &baseline, &height);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void render_sensor(esphome::display::Display& it, int x, int y,
|
||||||
|
float value, std::string unit,
|
||||||
|
const std::string& label) {
|
||||||
|
int normal_height = measure_height("X", id(normal_font));
|
||||||
|
char formatted[20];
|
||||||
|
if (std::isnan(value)) {
|
||||||
|
it.print(x, y, &id(normal_font), TextAlign::TOP_CENTER, "--");
|
||||||
|
} else {
|
||||||
|
char value_text[20];
|
||||||
|
if (std::abs(value) >= 1000) {
|
||||||
|
unit = "k" + unit;
|
||||||
|
value /= 1000;
|
||||||
|
}
|
||||||
|
if (std::abs(value) < 10) {
|
||||||
|
sprintf(value_text, "%.1f", value);
|
||||||
|
} else {
|
||||||
|
sprintf(value_text, "%.0f", value);
|
||||||
|
}
|
||||||
|
int value_width = measure_width(value_text, id(normal_font));
|
||||||
|
int unit_width = measure_width(unit.c_str(), id(small_font));
|
||||||
|
int width = value_width + unit_width + 3;
|
||||||
|
it.print(x - width / 2, y + normal_height, &id(normal_font),
|
||||||
|
TextAlign::BASELINE_LEFT, value_text);
|
||||||
|
it.print(x + width / 2 - unit_width, y + normal_height, &id(small_font),
|
||||||
|
TextAlign::BASELINE_LEFT, unit.c_str());
|
||||||
|
}
|
||||||
|
it.print(x, y + normal_height + 3, &id(small_font), TextAlign::TOP_CENTER,
|
||||||
|
label.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void render(esphome::display::Display& it) {
|
||||||
|
constexpr int kHeight = 540;
|
||||||
|
constexpr int kWidth = 960;
|
||||||
|
|
||||||
|
// Clock
|
||||||
|
it.strftime(25, 25, &id(clock_font), TextAlign::TOP_LEFT, "%H:%M",
|
||||||
|
id(rtc_time).now());
|
||||||
|
|
||||||
|
int right_width = measure_width("123||", id(normal_font));
|
||||||
|
render_sensor(it, kWidth - right_width / 2, kHeight * 0 / 10,
|
||||||
|
id(outside_temperature).state, "°C", "Outside");
|
||||||
|
render_sensor(it, kWidth - right_width / 2, kHeight * 3 / 10,
|
||||||
|
id(lounge_temperature).state, "°C", "Lounge");
|
||||||
|
render_sensor(it, kWidth - right_width / 2, kHeight * 6 / 10,
|
||||||
|
id(solar_power).state, "W", "Solar");
|
||||||
|
render_sensor(it, right_width / 2, kHeight * 6 / 10, id(uptime_sensor).state,
|
||||||
|
"s", "Uptime");
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
float level;
|
||||||
|
std::string icon;
|
||||||
|
} battery_levels[] = {
|
||||||
|
{10, "mdi-battery-alert-variant-outline"},
|
||||||
|
{40, "mdi-battery-low"},
|
||||||
|
{70, "mdi-battery-medium"},
|
||||||
|
{std::numeric_limits<float>::max(), "mdi-battery-high"},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Battery
|
||||||
|
float battery_level = id(m5paper_battery_level).state;
|
||||||
|
if (!std::isnan(battery_level)) {
|
||||||
|
for (const auto& level : battery_levels) {
|
||||||
|
if (battery_level <= level.level) {
|
||||||
|
it.print(910, 10, &id(battery_font),
|
||||||
|
id(material_icons_map)[level.icon].c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue