33 Commits

Author SHA1 Message Date
ff77818e30 Binaries & cross compilation 2024-08-11 21:07:44 +03:00
86c0515c46 CAN NOIP config load fix 2024-08-11 20:53:39 +03:00
293429d3a3 CAN driver - complete& working now 2024-08-11 19:13:42 +03:00
01ba615db8 mbus fix & binaries 2024-08-01 22:09:46 +03:00
1bfd2d98ef MODBUS: prefetch option for write reg (check-before-write),
AC: suppressing garbage status after CMD,
PID: NOT_FILTER_PID_OUT for repeating values^ by default
2024-08-01 20:19:33 +03:00
c8c7356fae DEFAULT_OTA_USERNAME DEFAULT_OTA_PASSWORD
compilation options
new 16u2 firmware
2024-05-20 01:22:02 +03:00
5b5e6e3d6a Ultrasonic sensor added
CAN driver logic/relability  improved
string -> itemCmd functionality added,
cold boot w/o config procedure improved
2024-04-12 11:00:42 +03:00
4fff338482 CAN DUE, relative items, CAN-MQTT brige 2024-03-30 08:29:53 +03:00
242db1552e Working with multiply MQTT brokers 2024-03-11 01:09:53 +03:00
0770e32b31 CAN driver v1 ESP&STM 2024-03-07 00:52:33 +03:00
535e1be274 CAN: config retrieving from master 2024-03-02 15:48:21 +03:00
3c9e30b28a STM32 chipId and 1st CAN driver prototype 2024-02-22 21:58:07 +03:00
1133883b25 NOIP compilation option & some inits 2024-02-19 16:07:13 +03:00
e7dfee51b1 Update README.md 2024-01-29 00:48:12 +03:00
9eb22f4ea9 Update README.md 2024-01-29 00:47:05 +03:00
09831781aa bins 2024-01-28 16:27:01 +03:00
340d54be09 sync 2024-01-28 16:20:45 +03:00
bcae3c9d50 artnet hung, sensors loop, inputs, multivent 2024-01-28 16:19:45 +03:00
1654f05bbe lh21 bins 2024-01-28 15:12:35 +03:00
99466f6e9f bins & cross-compilation 2024-01-28 15:10:56 +03:00
05ea031977 PID out, less logs, GET cfg fix, mbus concurr wrte 2024-01-28 12:05:10 +03:00
5ec57f0414 GET cmd refactored to operate in safe time 2024-01-27 15:03:11 +03:00
7ab78ab2ae binaries 2023-11-23 17:05:50 +03:00
4d909dd449 DMX IN integration with items 2023-11-20 20:55:37 +03:00
Климов Андрей Николаевич
b3db766b1a post-refactoring fix (Mercury) 2023-11-20 14:58:56 +03:00
080cdd4e22 LOG cleaning 2023-11-20 13:50:14 +03:00
91d5acf619 pre-release bins 2023-11-20 01:23:58 +03:00
454b88fbbf DMX IN fix (rollback to 2021) 2023-11-20 01:13:25 +03:00
6e283e32db decrease Timer0 int priority 2023-11-19 13:47:48 +03:00
18fbc783b5 templates, I2C/1Wire reset tune, bins 2023-11-18 00:57:12 +03:00
Климов Андрей Николаевич
5235bb67c1 timed command fx 2023-11-17 17:45:45 +03:00
9683e51c18 subitem retrieve fix, new loglev 9 for mbus trace 2023-11-15 11:02:53 +03:00
fd65c1a3a1 remove old stuff, templates for Emit strings 2023-11-12 23:21:11 +03:00
97 changed files with 59774 additions and 56452 deletions

View File

@@ -46,6 +46,7 @@ Scalability of Lighthub is virtually unlimited: Setup so many controllers you ne
* [Russian-language Wiki](https://www.lazyhome.ru/dokuwiki/doku.php) * [Russian-language Wiki](https://www.lazyhome.ru/dokuwiki/doku.php)
* [Compiling and flashing](https://github.com/anklimov/lighthub/wiki/Compiling-and-flashing) * [Compiling and flashing](https://github.com/anklimov/lighthub/wiki/Compiling-and-flashing)
* [Configuring](https://github.com/anklimov/lighthub/wiki/Configuring) * [Configuring](https://github.com/anklimov/lighthub/wiki/Configuring)
* [Browser Plugin for searching and configure controllers](https://github.com/anklimov/zeroconf-lighthub)
* [Channel commands](https://github.com/anklimov/lighthub/wiki/Channel-commands) * [Channel commands](https://github.com/anklimov/lighthub/wiki/Channel-commands)
* [OpenHab integration](https://github.com/anklimov/lighthub/wiki/OpenHab--integration) * [OpenHab integration](https://github.com/anklimov/lighthub/wiki/OpenHab--integration)
* [Doxygen developers documentation](https://anklimov.github.io/lighthub/docs/html/index.html) * [Doxygen developers documentation](https://anklimov.github.io/lighthub/docs/html/index.html)

View File

@@ -1,3 +1,4 @@
#
-DWIFI_ENABLE -DWIFI_ENABLE
-DDMX_DISABLE -DDMX_DISABLE
# - exeption in DMX.update/begin # - exeption in DMX.update/begin
@@ -12,7 +13,7 @@
-DARDUINO_OTA_MDNS_DISABLE -DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE -DMDNS_ENABLE
#- ArduinoMDNS didnt working #- ArduinoMDNS didnt working
-D CANDRV
-DMCP23017 -DMCP23017
-DMODBUS_TX_PIN=13 -DMODBUS_TX_PIN=13
#-DARTNET_ENABLE - udp rx errors (( #-DARTNET_ENABLE - udp rx errors ((

View File

@@ -31,7 +31,7 @@
#-D TWI_SDA=3 #-D TWI_SDA=3
##Slimming firmware to fit 50% of 1m flash ##Slimming firmware to fit 50% of 1m flash
-DDMX_DISABLE -DDMX_DISABLE
-UDARTNET_ENABLE -UARTNET_ENABLE
-DMODBUS_DISABLE -DMODBUS_DISABLE
-DMBUS_DISABLE -DMBUS_DISABLE
-DOWIRE_DISABLE -DOWIRE_DISABLE
@@ -44,3 +44,6 @@
-D BEARSSL_SSL_BASIC -D BEARSSL_SSL_BASIC
-D SPILED_DISABLE -D SPILED_DISABLE
-D PWM_DISABLE -D PWM_DISABLE
# WAK for HDC1080 (pin D3 on wemos is IO0)
-D WAK_PIN=D3

View File

@@ -40,3 +40,4 @@
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\" -D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
-D MERCURY_ENABLE -D MERCURY_ENABLE
#-D IPMODBUS #-D IPMODBUS
-D CONFIG_CLEAN_PIN=2

View File

@@ -0,0 +1,48 @@
-DNOIP
-DDMX_DISABLE
-DMODBUS_DISABLE
-DMBUS_DISABLE
-DOWIRE_DISABLE
-DDHT_DISABLE
-DCOUNTER_DISABLE
-DNO_HOMIE
-DCSSHDC_DISABLE
-DSPILED_DISABLE
-DAC_DISABLE
-DPID_DISABLE
-DMULTIVENT_DISABLE
-DMOTOR_DISABLE
-D CANDRV
-D THERMOSTAT_CHECK_PERIOD=5000
-D ULTRASONIC
-DENABLE_HWSERIAL1
-DdebugSerialPort=Serial1
#-DFLASH_BASE_ADDRESS
#-DFLASH_DATA_SECTOR
#-DFLASH_PAGE_NUMBER
# -D PIO_FRAMEWORK_ARDUINO_ENABLE_MASS_STORAGE
# -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC_AND_MSC
#-DdebugSerialPort=SerialUSB
#-DSerialPortType=USBSerial
#-DSERIAL_BAUD=0
#-DPIO_FRAMEWORK_ARDUINO_ENABLE_CDC
#-DUSBCON
#-DUSBD_VID=0x0483
#-DUSBD_PID=0x5740
#-DUSB_MANUFACTURER="Unknown"
#-DUSB_PRODUCT="\"BLUEPILL_F103C8\""
#-DHAL_PCD_MODULE_ENABLED
#-D USBD_USE_CDC
-D HAL_CAN_MODULE_ENABLED
#HAL_ETH_MODULE_DISABLED
#HAL_SD_MODULE_DISABLED
#HAL_DAC_MODULE_DISABLED
#-DMERCURY_ENABLE

View File

@@ -0,0 +1,513 @@
:20000000A7C00000C0C00000BEC00000BCC00000BAC00000B8C00000B6C00000B4C0000023
:20002000B2C00000B0C00000AEC00000B8C400007CC40000A8C00000A6C00000A4C0000082
:20004000A2C00000A0C000009EC000009CC000009AC0000098C0000096C0000021C100003A
:2000600092C0000090C000008EC000008CC000008AC0000088C0000086C0000084C0000028
:2000800082C0000080C000007EC000007CC000007AC0000078C000001201100102000008C4
:2000A00041233D0001000102DC0109023E00020100C0320904000001020201000524000143
:2000C00010042402060524060001070582030800FF09040100020A000000070504024000AC
:2000E0000107058302400001040309043203410072006400750069006E006F0020002800CA
:200100007700770077002E00610072006400750069006E006F002E0063006300290000003D
:200120002E03410072006400750069006E006F0020004400750065002000500072006F002D
:2001400067002E00200050006F0072007400000011241FBECFEFD2E0DEBFCDBF11E0A0E029
:20016000B1E0E2ECF0E102C005900D92A831B107D9F712E0A8E1B1E001C01D92A833B107E9
:20018000E1F722D19CC73CCF9C01DC01AE57BF4FED91FC91119741911196FC93EE93805885
:2001A0009F4FE817F90711F42D933C939FB7F894F901EC57FF4F8081815080839FBF842F6B
:2001C0000895882311F03F9A01C03F9847980895882311F046980895469A0895DF92EF9253
:2001E000FF920F931F93FC018489813019F0823019F404C010E303C010E001C010E283896E
:20020000823009F418608589873031F0883031F0863029F4126003C0146001C016601092A3
:20022000C9001092C8001092CA000785F088E188D288202F3F2D4E2D5D2D10921E01203B7C
:2002400084E0380780E0480780E0580719F481E080931E01CA01B90122E030E040E050E006
:2002600013D720583B47414E5F4FCA01B901202F3F2D4E2D5D2DE6D6215030403093CD00EB
:200280002093CC001093CA0082E08093C80088E98093C9001F910F91FF90EF90DF9008957E
:2002A0001F920F920FB60F9211242F938F939F93EF93FF939091CE008EB38430F1F4E091ED
:2002C000A201F091A3019083E091A201F091A301CF0101969093A3018093A201825A914079
:2002E00021F482E291E0928381839FB7F8948091A6018F5F8093A6019FBFFF91EF919F911B
:200300008F912F910F900FBE0F901F901895FC0140911A0140931B0180911C0180931D015F
:200320008585282F30E02170307020931A01858590E096958795817080931C0180911E013B
:20034000882339F088E790E090931901809318010895442341F4222331F082E390E09093EA
:20036000190180931801089580E091E001C680E091E0B4C51F9384B7877F84BF18E10FB6C4
:20038000F89410936000109260000FBE80E019DF469A3E9A87E690E09093CD008093CC0043
:2003A00086E08093CA001092C8001093C900539A5A9A8AB180638AB98BB180638BB9AAD203
:2003C00084E085BD1F9108950F931F93CF93DF93D1DF2FB7F89487EA91E09093280280939E
:2003E000270290932A02809329022FBF2FB7F89482E291E09093A3018093A2019093A501CC
:200400008093A4012FBF7894C7EAD1E003E08FB7F89490912B028FBF903809F180E091E0E4
:20042000D3D497FD1CC0E0912702F09128028083E0912702F0912802CF0101969093280264
:20044000809327028752924011F4D283C1839FB7F89480912B028F5F80932B029FBF8FB725
:20046000F8941091A6018FBFA89903C0113608F456C0A89A8091A601882361F05D9800937F
:200480001F0108C082E291E07FDE682F80E091E001D511501123B1F780911F01882351F0AA
:2004A00080911F01815080931F0180911F01882309F45D9A80912001882351F080912001E7
:2004C00081508093200180912001882309F45C9A809118019091190118161906E4F4CC975A
:2004E000CD9710F481E001C080E072DE80911801909119010197C29710F481E001C080E0E6
:2005000060DE80911801909119010197909319018093180104C080E05BDE80E052DE8FB704
:20052000F89490912B028FBF992369F087EA91E02BDE982F8091C80085FFFCCF9093CE00B3
:200540005C980093200180E091E095D42AD45FCFDA01923049F0933061F09130F9F4E8E924
:20056000F0E022E130E01EC0EAEAF0E02EE330E019C0813049F0813018F0823079F408C092
:20058000E8EEF0E0849107C0ECEEF0E0849103C0E0E2F1E08491282F30E004C0E0E0F0E0F4
:2005A00020E030E0ED93FC93C901089528E030E040E003C04F5F220F331F28173907D0F347
:2005C000842F8295807F08958093E9008091EB0081608093EB001092ED006093EC0040939D
:2005E000ED008091EE00881F8827881F08951092F40090E09093E9001092F0001092E80047
:200600001092ED008091EB008E7F8093EB009F5F953081F708958091300288238CF403C03B
:200620008EB38823B1F08091E80082FFF9CF8091E8008B778093E80008958EB3882349F033
:200640008091E80080FFF9CF8091E8008E778093E800089594E68091EC0080FF05C08091F8
:20066000E80080FF05C023C08091E80082FD1FC08EB3882311F482E008958EB3853011F429
:2006800083E008958091EB0085FF02C081E008958091E10082FFDFCF8091E1008B7F8093EA
:2006A000E100992311F484E008959150D4CF80E008959C014091360250913702461757079B
:2006C00018F4F90120E038C06115710511F0AB01F8CF8091E8008E778093E80040E050E073
:2006E000F0CF8091E80083FF02C081E008958091E80082FD2DC08EB3882381F18EB3853047
:2007000079F18091E80080FF17C09091F20006C081918093F100415050409F5F4115510566
:2007200011F09830A8F320E0983009F421E08091E8008E778093E8004115510591F622231E
:2007400081F606C08EB3882349F08EB3853041F08091E80082FFF6CF80E0089582E00895D5
:2007600083E008959C0140913602509137024617570710F490E03BC06115710511F0AB01F6
:20078000F9CF8091E8008E778093E80040E050E0F1CF8091E80083FF02C081E0089580913C
:2007A000E80082FD30C08EB3882399F18EB3853091F18091E80080FF1AC08091F20009C0D6
:2007C000F9012F5F3F4FE491E093F100415050408F5F4115510511F0883090F390E088300B
:2007E00009F491E08091E8008E778093E8004115510579F6992369F606C08EB3882349F071
:200800008EB3853041F08091E80082FFF6CF80E0089582E0089583E008959C0161157105ED
:2008200029F48091E8008B778093E800F90120C08091E80083FF02C081E008958EB38823A4
:2008400039F18EB3853031F18091E80082FFF0CF06C08091F10081936150704021F08091BE
:20086000F2008823B1F78091E8008B778093E80061157105E9F606C08EB3882349F08EB346
:20088000853041F08091E80080FFF6CF80E0089582E0089583E0089542D044D01EBA109299
:2008A0002E0210922D0210922C0284E089BD89B5826089BD09B400FEFDCF8091D800982F20
:2008C0009F779093D80080688093D800809163008E7F809363008091D8008F7D8093D8005D
:2008E0008091E0008E7F8093E0008091E1008E7F8093E1008091E20081608093E20080913A
:20090000E100877F8093E1008091E20088608093E2000895C1DF81E080932F02089510920B
:20092000E20008951092E10008951F920F920FB60F9211241F932F933F934F935F936F930F
:200940007F938F939F93AF93BF93EF93FF93E9EEF0E0108117701082E0EFF0E08081877F92
:2009600080837894C3D0F894A9EEB0E01C92E0EFF0E08081886080831C93FF91EF91BF91DA
:20098000AF919F918F917F916F915F914F913F912F911F910F900FBE0F901F9018951F928F
:2009A0000F920FB60F9211242F933F934F935F936F937F938F939F93AF93BF93EF93FF9383
:2009C0008091E10080FF1BC08091E20080FF17C08091E1008E7F8093E1008091E2008E7F8F
:2009E0008093E2008091E20080618093E2008091D80080628093D80019BC1EBAD1D1809123
:200A0000E10084FF29C08091E20084FF25C084E089BD89B5826089BD09B400FEFDCF809186
:200A2000D8008F7D8093D8008091E1008F7E8093E1008091E2008F7E8093E2008091E2000C
:200A400081608093E20080912E02882311F481E001C084E08EBBA4D18091E10083FF27C030
:200A60008091E20083FF23C08091E100877F8093E10082E08EBB10922E028091E1008E7FB6
:200A80008093E1008091E2008E7F8093E2008091E20080618093E200AADD80E060E042E05B
:200AA00093DD8091F00088608093F00079D18091E10082FF0AC08091E20082FF06C0809108
:200AC000E1008B7F8093E1006BD1FF91EF91BF91AF919F918F917F916F915F914F913F915B
:200AE0002F910F900FBE0F901F9018951F93DF93CF93CDB7DEB7AC970FB6F894DEBF0FBE32
:200B0000CDBFE0E3F2E08091F100819322E0E833F207C9F78091300230913102353009F42F
:200B200087C0363040F43130C9F1313070F0333009F01DC133C0383009F4EFC0393009F451
:200B4000FEC0363009F013C192C0803821F0823809F00DC108C090912C0280912D02882306
:200B600099F0926011C08091340287708093E9008091EB0090E025E0969587952A95E1F7A0
:200B8000982F91701092E9008091E800877F8093E8009093F1001092F100CAC0882319F023
:200BA000823009F0E4C090E08F719070009721F0029709F0DDC00CC080913202813009F0E4
:200BC000D7C010922D02333069F580932D022AC080913202882331F520913402277009F42F
:200BE000C7C02093E9008091EB0080FFC1C0333021F48091EB00806213C08091EB008061D0
:200C00008093EB0081E090E002C0880F991F2A95E2F78093EA001092EA008091EB008860EF
:200C20008093EB001092E9008091E800877F83C0882309F09CC0109132028091E800877F15
:200C40008093E800E8DC04C08EB3882309F490C08091E80080FFF8CF812F8F7711F492E06C
:200C600001C093E09EBB80688093E30081C08058823008F07CC0809132029091330223E06C
:200C80008C3D920799F55FB7F894DE0115964EE020E030E061E2E42FF0E060935700849175
:200CA00020FF03C082958F704F5F982F9F70892F805D8A3308F0895F8C9311961C9211976A
:200CC0002F5F3F4F12962431310529F75FBF8AE28B8383E08C838091E800877F8093E800A1
:200CE000CE0103966AE270E0E4DC11C060913402AE014F5F5F4F2CDCBC010097C9F1809106
:200D0000E800877F8093E80089819A812BDD8091E8008B778093E8002BC0803841F58091DD
:200D2000E800877F8093E80080912E028093F1008091E8008E778093E8006DDC19C08823BF
:200D4000B1F490913202923098F48091E800877F8093E80090932E025EDC80912E028823D8
:200D600011F483E001C084E08EBB01DB01C0FCDA8091E80083FF0AC08091EB0080628093F4
:200D8000EB008091E800877F8093E800AC960FB6F894DEBF0FBECDBFCF91DF911F910895C8
:200DA00008951F938EB3882361F01091E9001092E9008091E80083FF01C098DE17701093B6
:200DC000E9001F9108950895FC018EB3843021F587859089A189B2890097A105B105E1F0EA
:200DE00085818093E9008091E80082FF15C08091F200882319F42FEF3FEF04C08091F100D5
:200E0000282F30E08091F200882341F48091E8008B778093E80002C02FEF3FEFC90108951D
:200E2000FC018EB3843011F587859089A189B2890097A105B105D1F081818093E90080916D
:200E4000F2008823A9F09091E8008091E8008E778093E80095FD0CC0FDDB982F882349F475
:200E60008091E8008E778093E80003C092E001C090E0892F0895FC018EB3843051F487857B
:200E80009089A189B2890097A105B10511F0CF01C7CF08951F93FC01162F8EB38430D9F427
:200EA00087859089A189B2890097A105B10599F081818093E9008091E80085FD08C08091DA
:200EC000E8008E778093E800C5DB882329F41093F10080E001C082E01F9108950F931F930A
:200EE000CF93DF93EC010D96FC0189E0DF011D928A95E9F72A813B8109818C81882311F4EC
:200F000010E001C014E0C90151DB182B1260802F61E8412F59DB882329F12E813F810D8123
:200F20008885882311F410E001C014E0C9013EDB182B1260802F60E8412F46DB882391F003
:200F40002A853B8509858C85882311F410E001C014E0C9012BDB182B1260802F61EC412F3D
:200F600033DB01C080E0DF91CF911F910F910895CF93DF93EC018091E80083FF60C0888120
:200F800090E020913402309135022817390709F056C080913102813261F0823220F48032B2
:200FA00009F04DC019C0823269F1833209F047C038C080913002813A09F041C08091E800A6
:200FC000877F8093E800CE010F9667E070E071DB8091E8008B7713C080913002813279F587
:200FE0008091E800877F8093E800CE010F9667E070E013DCCE01F2D88091E8008E77809353
:20100000E8001DC0809130028132C9F48091E800877F8093E800809132028D87CE0177D9E6
:201020000DC080913002813251F48091E800877F8093E800CE0160913202C5DEECDADF91E1
:20104000CF910895A1E21A2EAA1BBB1BFD010DC0AA1FBB1FEE1FFF1FA217B307E407F5073A
:2010600020F0A21BB30BE40BF50B661F771F881F991F1A9469F760957095809590959B019E
:20108000AC01BD01CF01089597FB092E05260ED057FD04D0D7DF0AD0001C38F450954095EC
:2010A000309521953F4F4F4F5F4F0895F6F790958095709561957F4F8F4F9F4F0895F89459
:2010C000FFCF000340000004400000020800000000000000000000001400FFFFFFFFFFFFA3
:2010E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:20110000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
:20112000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
:20114000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
:20116000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
:20118000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
:2011A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
:2011C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
:2011E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F
:20120000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE
:20122000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE
:20124000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE
:20126000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E
:20128000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E
:2012A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E
:2012C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E
:2012E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E
:20130000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED
:20132000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
:20134000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD
:20136000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D
:20138000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D
:2013A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D
:2013C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D
:2013E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D
:20140000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC
:20142000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC
:20144000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC
:20146000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C
:20148000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C
:2014A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C
:2014C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C
:2014E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C
:20150000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB
:20152000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB
:20154000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB
:20156000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B
:20158000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B
:2015A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B
:2015C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B
:2015E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B
:20160000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA
:20162000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA
:20164000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA
:20166000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A
:20168000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A
:2016A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A
:2016C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A
:2016E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A
:20170000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9
:20172000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9
:20174000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9
:20176000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89
:20178000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69
:2017A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49
:2017C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29
:2017E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09
:20180000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8
:20182000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8
:20184000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8
:20186000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88
:20188000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
:2018A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48
:2018C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28
:2018E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08
:20190000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7
:20192000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7
:20194000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7
:20196000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87
:20198000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67
:2019A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47
:2019C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27
:2019E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07
:201A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6
:201A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6
:201A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6
:201A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86
:201A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
:201AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46
:201AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26
:201AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06
:201B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5
:201B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5
:201B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5
:201B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85
:201B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65
:201BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45
:201BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25
:201BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05
:201C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4
:201C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4
:201C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4
:201C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
:201C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64
:201CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44
:201CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24
:201CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04
:201D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3
:201D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3
:201D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3
:201D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83
:201D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63
:201DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43
:201DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23
:201DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03
:201E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2
:201E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2
:201E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2
:201E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82
:201E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62
:201EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42
:201EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
:201EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
:201F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1
:201F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1
:201F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
:201F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
:201F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
:201FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
:201FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
:201FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
:20200000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
:20202000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0
:20204000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0
:20206000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80
:20208000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60
:2020A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40
:2020C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20
:2020E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00
:20210000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF
:20212000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF
:20214000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F
:20216000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F
:20218000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F
:2021A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F
:2021C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F
:2021E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
:20220000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE
:20222000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE
:20224000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E
:20226000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E
:20228000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E
:2022A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E
:2022C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E
:2022E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE
:20230000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD
:20232000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD
:20234000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D
:20236000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D
:20238000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D
:2023A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D
:2023C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D
:2023E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD
:20240000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC
:20242000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC
:20244000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C
:20246000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C
:20248000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C
:2024A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C
:2024C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C
:2024E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC
:20250000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB
:20252000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB
:20254000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B
:20256000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B
:20258000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B
:2025A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B
:2025C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B
:2025E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB
:20260000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA
:20262000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA
:20264000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A
:20266000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A
:20268000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A
:2026A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A
:2026C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A
:2026E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA
:20270000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9
:20272000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9
:20274000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99
:20276000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79
:20278000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59
:2027A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39
:2027C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19
:2027E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9
:20280000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8
:20282000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8
:20284000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98
:20286000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78
:20288000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58
:2028A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF38
:2028C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18
:2028E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8
:20290000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7
:20292000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7
:20294000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97
:20296000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77
:20298000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57
:2029A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37
:2029C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17
:2029E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7
:202A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6
:202A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6
:202A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96
:202A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76
:202A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56
:202AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36
:202AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16
:202AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6
:202B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5
:202B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5
:202B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95
:202B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75
:202B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55
:202BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35
:202BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15
:202BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5
:202C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4
:202C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4
:202C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94
:202C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74
:202C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54
:202CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34
:202CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14
:202CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4
:202D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3
:202D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3
:202D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93
:202D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73
:202D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53
:202DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33
:202DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13
:202DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3
:202E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2
:202E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2
:202E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92
:202E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72
:202E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52
:202EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32
:202EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12
:202EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2
:202F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1
:202F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1
:202F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91
:202F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71
:202F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51
:202FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31
:202FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11
:202FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1
:20300000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0
:20302000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
:20304000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90
:20306000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70
:20308000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50
:2030A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30
:2030C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10
:2030E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0
:20310000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF
:20312000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF
:20314000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F
:20316000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F
:20318000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F
:2031A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F
:2031C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F
:2031E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF
:20320000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE
:20322000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE
:20324000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E
:20326000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E
:20328000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E
:2032A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E
:2032C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E
:2032E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE
:20330000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD
:20332000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD
:20334000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D
:20336000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D
:20338000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D
:2033A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D
:2033C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D
:2033E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED
:20340000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC
:20342000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC
:20344000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C
:20346000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C
:20348000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C
:2034A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C
:2034C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C
:2034E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC
:20350000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB
:20352000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB
:20354000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B
:20356000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B
:20358000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B
:2035A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B
:2035C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B
:2035E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB
:20360000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA
:20362000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA
:20364000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A
:20366000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A
:20368000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A
:2036A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A
:2036C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A
:2036E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA
:20370000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9
:20372000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9
:20374000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89
:20376000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69
:20378000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49
:2037A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29
:2037C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09
:2037E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9
:20380000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8
:20382000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8
:20384000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88
:20386000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68
:20388000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48
:2038A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28
:2038C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08
:2038E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8
:20390000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7
:20392000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7
:20394000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87
:20396000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67
:20398000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47
:2039A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27
:2039C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07
:2039E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7
:203A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6
:203A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6
:203A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86
:203A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
:203A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46
:203AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26
:203AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06
:203AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6
:203B0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC5
:203B2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA5
:203B4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF85
:203B6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF65
:203B8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF45
:203BA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF25
:203BC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF05
:203BE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5
:203C0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC4
:203C2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA4
:203C4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF84
:203C6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF64
:203C8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF44
:203CA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF24
:203CC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF04
:203CE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE4
:203D0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC3
:203D2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA3
:203D4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF83
:203D6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF63
:203D8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF43
:203DA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF23
:203DC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF03
:203DE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE3
:203E0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC2
:203E2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA2
:203E4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF82
:203E6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF62
:203E8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF42
:203EA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22
:203EC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF02
:203EE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE2
:203F0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1
:203F2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1
:203F4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81
:203F6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61
:203F8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41
:203FA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF21
:203FC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01
:203FE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1
:00000001FF

View File

@@ -1,137 +0,0 @@
:20000000A7C00000C0C00000BEC00000BCC00000BAC00000B8C00000B6C00000B4C0000023
:20002000B2C00000B0C00000AEC00000C1C4000085C40000A8C00000A6C00000A4C0000070
:20004000A2C00000A0C000009EC000009CC000009AC0000098C0000096C0000021C100003A
:2000600092C0000090C000008EC000008CC000008AC0000088C0000086C0000084C0000028
:2000800082C0000080C000007EC000007CC000007AC0000078C000001201100102000008C4
:2000A00041233D0001000102DC0109023E00020100C0320904000001020201000524000143
:2000C00010042402060524060001070582030800FF09040100020A000000070504024000AC
:2000E0000107058302400001040309043203410072006400750069006E006F0020002800CA
:200100007700770077002E00610072006400750069006E006F002E0063006300290000003D
:200120002E03410072006400750069006E006F0020004400750065002000500072006F002D
:2001400067002E00200050006F0072007400000011241FBECFEFD2E0DEBFCDBF11E0A0E029
:20016000B1E0E4EDF0E102C005900D92A831B107D9F712E0A8E1B1E001C01D92A833B107E6
:20018000E1F72BD1A5C73CCF9C01DC01AE57BF4FED91FC91119741911196FC93EE93805873
:2001A0009F4FE817F90711F42D933C939FB7F894F901EC57FF4F8081815080839FBF842F6B
:2001C0000895882311F03F9A01C03F9847980895882311F046980895469A0895DF92EF9253
:2001E000FF920F931F93FC018489813019F0823019F404C010E303C010E001C010E283896E
:20020000823009F418608589873031F0883031F0863029F4126003C0146001C016601092A3
:20022000C9001092C8001092CA000785F088E188D288202F3F2D4E2D5D2D10921E01203B7C
:2002400084E0380780E0480780E0580719F481E080931E01CA01B90122E030E040E050E006
:200260001CD720583B47414E5F4FCA01B901202F3F2D4E2D5D2DEFD6215030403093CD00D9
:200280002093CC001093CA0082E08093C80088E98093C9001F910F91FF90EF90DF9008957E
:2002A0001F920F920FB60F9211242F938F939F93EF93FF939091CE008EB38430F1F4E091ED
:2002C000A201F091A3019083E091A201F091A301CF0101969093A3018093A201825A914079
:2002E00021F482E291E0928381839FB7F8948091A6018F5F8093A6019FBFFF91EF919F911B
:200300008F912F910F900FBE0F901F901895FC0140911A0140931B0180911C0180931D015F
:200320008585282F30E02170307020931A01858590E096958795817080931C0180911E013B
:20034000882339F088E790E090931901809318010895442341F4222331F082E390E09093EA
:20036000190180931801089580E091E00AC680E091E0BDC584B7877F84BF88E10FB6F89468
:2003800080936000109260000FBE81E01ADF16BC83E085BD86B58831E8F315BC16BC80E078
:2003A00010DF469A3E9A87E690E09093CD008093CC0086E08093CA001092C80088E18093C1
:2003C000C900539A5A9A8AB180638AB98BB180638BB9A9D284E085BD08950F931F93CF933B
:2003E000DF93C8DF2FB7F89487EA91E0909328028093270290932A02809329022FBF2FB7A6
:20040000F89482E291E09093A3018093A2019093A5018093A4012FBF7894C7EAD1E003E03E
:200420008FB7F89490912B028FBF903809F180E091E0D3D497FD1CC0E0912702F09128025F
:200440008083E0912702F0912802CF01019690932802809327028752924011F4D283C1831B
:200460009FB7F89480912B028F5F80932B029FBF8FB7F8941091A6018FBFA89903C011361D
:2004800008F456C0A89A8091A601882361F05D9800931F0108C082E291E076DE682F80E0C4
:2004A00091E001D511501123B1F780911F01882351F080911F01815080931F0180911F0135
:2004C000882309F45D9A80912001882351F08091200181508093200180912001882309F44E
:2004E0005C9A809118019091190118161906E4F4CC97CD9710F481E001C080E069DE8091D7
:200500001801909119010197C29710F481E001C080E057DE809118019091190101979093BB
:2005200019018093180104C080E052DE80E049DE8FB7F89490912B028FBF992369F087EAA6
:2005400091E022DE982F8091C80085FFFCCF9093CE005C980093200180E091E095D42AD46A
:200560005FCFDA01923049F0933061F09130F9F4E8E9F0E022E130E01EC0EAEAF0E02EE36E
:2005800030E019C0813049F0813018F0823079F408C0E8EEF0E0849107C0ECEEF0E08491A7
:2005A00003C0E0E2F1E08491282F30E004C0E0E0F0E020E030E0ED93FC93C901089528E087
:2005C00030E040E003C04F5F220F331F28173907D0F3842F8295807F08958093E900809142
:2005E000EB0081608093EB001092ED006093EC004093ED008091EE00881F8827881F08956A
:200600001092F40090E09093E9001092F0001092E8001092ED008091EB008E7F8093EB0016
:200620009F5F953081F708958091300288238CF403C08EB38823B1F08091E80082FFF9CFE2
:200640008091E8008B778093E80008958EB3882349F08091E80080FFF9CF8091E8008E77A4
:200660008093E800089594E68091EC0080FF05C08091E80080FF05C023C08091E80082FD8F
:200680001FC08EB3882311F482E008958EB3853011F483E008958091EB0085FF02C081E0ED
:2006A00008958091E10082FFDFCF8091E1008B7F8093E100992311F484E008959150D4CF46
:2006C00080E008959C0140913602509137024617570718F4F90120E038C06115710511F0B7
:2006E000AB01F8CF8091E8008E778093E80040E050E0F0CF8091E80083FF02C081E0089544
:200700008091E80082FD2DC08EB3882381F18EB3853079F18091E80080FF17C09091F20054
:2007200006C081918093F100415050409F5F4115510511F09830A8F320E0983009F421E0E8
:200740008091E8008E778093E8004115510591F6222381F606C08EB3882349F08EB38530D0
:2007600041F08091E80082FFF6CF80E0089582E0089583E008959C0140913602509137024D
:200780004617570710F490E03BC06115710511F0AB01F9CF8091E8008E778093E80040E0B5
:2007A00050E0F1CF8091E80083FF02C081E008958091E80082FD30C08EB3882399F18EB3EF
:2007C000853091F18091E80080FF1AC08091F20009C0F9012F5F3F4FE491E093F100415044
:2007E00050408F5F4115510511F0883090F390E0883009F491E08091E8008E778093E80004
:200800004115510579F6992369F606C08EB3882349F08EB3853041F08091E80082FFF6CF51
:2008200080E0089582E0089583E008959C016115710529F48091E8008B778093E800F90126
:2008400020C08091E80083FF02C081E008958EB3882339F18EB3853031F18091E80082FFD5
:20086000F0CF06C08091F10081936150704021F08091F2008823B1F78091E8008B77809307
:20088000E80061157105E9F606C08EB3882349F08EB3853041F08091E80080FFF6CF80E0F6
:2008A000089582E0089583E0089542D044D01EBA10922E0210922D0210922C0284E089BD81
:2008C00089B5826089BD09B400FEFDCF8091D800982F9F779093D80080688093D800809186
:2008E00063008E7F809363008091D8008F7D8093D8008091E0008E7F8093E0008091E1004F
:200900008E7F8093E1008091E20081608093E2008091E100877F8093E1008091E200886046
:200920008093E2000895C1DF81E080932F0208951092E20008951092E10008951F920F92B0
:200940000FB60F9211241F932F933F934F935F936F937F938F939F93AF93BF93EF93FF93D2
:20096000E9EEF0E0108117701082E0EFF0E08081877F80837894C3D0F894A9EEB0E01C927D
:20098000E0EFF0E08081886080831C93FF91EF91BF91AF919F918F917F916F915F914F914D
:2009A0003F912F911F910F900FBE0F901F9018951F920F920FB60F9211242F933F934F932D
:2009C0005F936F937F938F939F93AF93BF93EF93FF938091E10080FF1BC08091E20080FF57
:2009E00017C08091E1008E7F8093E1008091E2008E7F8093E2008091E20080618093E2006F
:200A00008091D80080628093D80019BC1EBAD1D18091E10084FF29C08091E20084FF25C018
:200A200084E089BD89B5826089BD09B400FEFDCF8091D8008F7D8093D8008091E1008F7E40
:200A40008093E1008091E2008F7E8093E2008091E20081608093E20080912E02882311F4F3
:200A600081E001C084E08EBBA4D18091E10083FF27C08091E20083FF23C08091E100877F87
:200A80008093E10082E08EBB10922E028091E1008E7F8093E1008091E2008E7F8093E200FD
:200AA0008091E20080618093E200AADD80E060E042E093DD8091F00088608093F00079D17E
:200AC0008091E10082FF0AC08091E20082FF06C08091E1008B7F8093E1006BD1FF91EF9163
:200AE000BF91AF919F918F917F916F915F914F913F912F910F900FBE0F901F9018951F938D
:200B0000DF93CF93CDB7DEB7AC970FB6F894DEBF0FBECDBFE0E3F2E08091F100819322E0B1
:200B2000E833F207C9F78091300230913102353009F487C0363040F43130C9F1313070F08B
:200B4000333009F01DC133C0383009F4EFC0393009F4FEC0363009F013C192C0803821F0E2
:200B6000823809F00DC108C090912C0280912D02882399F0926011C0809134028770809355
:200B8000E9008091EB0090E025E0969587952A95E1F7982F91701092E9008091E800877FCB
:200BA0008093E8009093F1001092F100CAC0882319F0823009F0E4C090E08F7190700097FF
:200BC00021F0029709F0DDC00CC080913202813009F0D7C010922D02333069F580932D02AF
:200BE0002AC080913202882331F520913402277009F4C7C02093E9008091EB0080FFC1C05B
:200C0000333021F48091EB00806213C08091EB0080618093EB0081E090E002C0880F991FEE
:200C20002A95E2F78093EA001092EA008091EB0088608093EB001092E9008091E800877F27
:200C400083C0882309F09CC0109132028091E800877F8093E800E8DC04C08EB3882309F411
:200C600090C08091E80080FFF8CF812F8F7711F492E001C093E09EBB80688093E30081C00C
:200C80008058823008F07CC0809132029091330223E08C3D920799F55FB7F894DE011596DC
:200CA0004EE020E030E061E2E42FF0E060935700849120FF03C082958F704F5F982F9F70F5
:200CC000892F805D8A3308F0895F8C9311961C9211972F5F3F4F12962431310529F75FBF39
:200CE0008AE28B8383E08C838091E800877F8093E800CE0103966AE270E0E4DC11C0609188
:200D00003402AE014F5F5F4F2CDCBC010097C9F18091E800877F8093E80089819A812BDD55
:200D20008091E8008B778093E8002BC0803841F58091E800877F8093E80080912E02809396
:200D4000F1008091E8008E778093E8006DDC19C08823B1F490913202923098F48091E8009B
:200D6000877F8093E80090932E025EDC80912E02882311F483E001C084E08EBBF8DA01C090
:200D8000F3DA8091E80083FF0AC08091EB0080628093EB008091E800877F8093E800AC9629
:200DA0000FB6F894DEBF0FBECDBFCF91DF911F91089508951F938EB3882361F01091E900B9
:200DC0001092E9008091E80083FF01C098DE17701093E9001F9108950895FC018EB38430E7
:200DE00021F587859089A189B2890097A105B105E1F085818093E9008091E80082FF15C03E
:200E00008091F200882319F42FEF3FEF04C08091F100282F30E08091F200882341F48091AA
:200E2000E8008B778093E80002C02FEF3FEFC9010895FC018EB3843011F587859089A18911
:200E4000B2890097A105B105D1F081818093E9008091F2008823A9F09091E8008091E8005C
:200E60008E778093E80095FD0CC0FDDB982F882349F48091E8008E778093E80003C092E05F
:200E800001C090E0892F0895FC018EB3843051F487859089A189B2890097A105B10511F017
:200EA000CF01C7CF08951F93FC01162F8EB38430D9F487859089A189B2890097A105B105FC
:200EC00099F081818093E9008091E80085FD08C08091E8008E778093E800C5DB882329F4E7
:200EE0001093F10080E001C082E01F9108950F931F93CF93DF93EC010D96FC0189E0DF0190
:200F00001D928A95E9F72A813B8109818C81882311F410E001C014E0C90151DB182B126025
:200F2000802F61E8412F59DB882329F12E813F810D818885882311F410E001C014E0C90127
:200F40003EDB182B1260802F60E8412F46DB882391F02A853B8509858C85882311F410E061
:200F600001C014E0C9012BDB182B1260802F61EC412F33DB01C080E0DF91CF911F910F917C
:200F80000895CF93DF93EC018091E80083FF60C0888190E020913402309135022817390781
:200FA00009F056C080913102813261F0823220F4803209F04DC019C0823269F1833209F0C5
:200FC00047C038C080913002813A09F041C08091E800877F8093E800CE010F9667E070E015
:200FE00071DB8091E8008B7713C080913002813279F58091E800877F8093E800CE010F9605
:2010000067E070E013DCCE01E9D88091E8008E778093E8001DC0809130028132C9F4809120
:20102000E800877F8093E800809132028D87CE016ED90DC080913002813251F48091E80057
:20104000877F8093E800CE0160913202C5DEECDADF91CF910895A1E21A2EAA1BBB1BFD0161
:201060000DC0AA1FBB1FEE1FFF1FA217B307E407F50720F0A21BB30BE40BF50B661F771FE6
:20108000881F991F1A9469F760957095809590959B01AC01BD01CF01089597FB092E052647
:2010A0000ED057FD04D0D7DF0AD0001C38F450954095309521953F4F4F4F5F4F0895F6F7B9
:2010C00090958095709561957F4F8F4F9F4F0895F894FFCF000340000004400000020800B9
:0C10E000000000000000000000001400F0
:00000001FF

View File

@@ -1,137 +0,0 @@
:20000000A7C00000C0C00000BEC00000BCC00000BAC00000B8C00000B6C00000B4C0000023
:20002000B2C00000B0C00000AEC00000C1C4000085C40000A8C00000A6C00000A4C0000070
:20004000A2C00000A0C000009EC000009CC000009AC0000098C0000096C0000021C100003A
:2000600092C0000090C000008EC000008CC000008AC0000088C0000086C0000084C0000028
:2000800082C0000080C000007EC000007CC000007AC0000078C000001201100102000008C4
:2000A00041233D0001000102DC0109023E00020100C0320904000001020201000524000143
:2000C00010042402060524060001070582030800FF09040100020A000000070504024000AC
:2000E0000107058302400001040309043203410072006400750069006E006F0020002800CA
:200100007700770077002E00610072006400750069006E006F002E0063006300290000003D
:200120002E03410072006400750069006E006F0020004400750065002000500072006F002D
:2001400067002E00200050006F0072007400000011241FBECFEFD2E0DEBFCDBF11E0A0E029
:20016000B1E0E4EDF0E102C005900D92A831B107D9F712E0A8E1B1E001C01D92A833B107E6
:20018000E1F72BD1A5C73CCF9C01DC01AE57BF4FED91FC91119741911196FC93EE93805873
:2001A0009F4FE817F90711F42D933C939FB7F894F901EC57FF4F8081815080839FBF842F6B
:2001C0000895882311F03F9A01C03F9847980895882311F046980895469A0895DF92EF9253
:2001E000FF920F931F93FC018489813019F0823019F404C010E303C010E001C010E283896E
:20020000823009F418608589873031F0883031F0863029F4126003C0146001C016601092A3
:20022000C9001092C8001092CA000785F088E188D288202F3F2D4E2D5D2D10921E01203B7C
:2002400084E0380780E0480780E0580719F481E080931E01CA01B90122E030E040E050E006
:200260001CD720583B47414E5F4FCA01B901202F3F2D4E2D5D2DEFD6215030403093CD00D9
:200280002093CC001093CA0082E08093C80088E98093C9001F910F91FF90EF90DF9008957E
:2002A0001F920F920FB60F9211242F938F939F93EF93FF939091CE008EB38430F1F4E091ED
:2002C000A201F091A3019083E091A201F091A301CF0101969093A3018093A201825A914079
:2002E00021F482E291E0928381839FB7F8948091A6018F5F8093A6019FBFFF91EF919F911B
:200300008F912F910F900FBE0F901F901895FC0140911A0140931B0180911C0180931D015F
:200320008585282F30E02170307020931A01858590E096958795817080931C0180911E013B
:20034000882339F088E790E090931901809318010895442341F4222331F082E390E09093EA
:20036000190180931801089580E091E00AC680E091E0BDC584B7877F84BF88E10FB6F89468
:2003800080936000109260000FBE81E01ADF16BC83E085BD86B58831E8F315BC16BC80E078
:2003A00010DF469A3E9A87E690E09093CD008093CC0086E08093CA001092C80088E18093C1
:2003C000C900539A5A9A8AB180638AB98BB180638BB9A9D284E085BD08950F931F93CF933B
:2003E000DF93C8DF2FB7F89487EA91E0909328028093270290932A02809329022FBF2FB7A6
:20040000F89482E291E09093A3018093A2019093A5018093A4012FBF7894C7EAD1E003E03E
:200420008FB7F89490912B028FBF903809F180E091E0D3D497FD1CC0E0912702F09128025F
:200440008083E0912702F0912802CF01019690932802809327028752924011F4D283C1831B
:200460009FB7F89480912B028F5F80932B029FBF8FB7F8941091A6018FBFA89903C011361D
:2004800008F456C0A89A8091A601882361F05D9800931F0108C082E291E076DE682F80E0C4
:2004A00091E001D511501123B1F780911F01882351F080911F01815080931F0180911F0135
:2004C000882309F45D9A80912001882351F08091200181508093200180912001882309F44E
:2004E0005C9A809118019091190118161906E4F4CC97CD9710F481E001C080E069DE8091D7
:200500001801909119010197C29710F481E001C080E057DE809118019091190101979093BB
:2005200019018093180104C080E052DE80E049DE8FB7F89490912B028FBF992369F087EAA6
:2005400091E022DE982F8091C80085FFFCCF9093CE005C980093200180E091E095D42AD46A
:200560005FCFDA01923049F0933061F09130F9F4E8E9F0E022E130E01EC0EAEAF0E02EE36E
:2005800030E019C0813049F0813018F0823079F408C0E8EEF0E0849107C0ECEEF0E08491A7
:2005A00003C0E0E2F1E08491282F30E004C0E0E0F0E020E030E0ED93FC93C901089528E087
:2005C00030E040E003C04F5F220F331F28173907D0F3842F8295807F08958093E900809142
:2005E000EB0081608093EB001092ED006093EC004093ED008091EE00881F8827881F08956A
:200600001092F40090E09093E9001092F0001092E8001092ED008091EB008E7F8093EB0016
:200620009F5F953081F708958091300288238CF403C08EB38823B1F08091E80082FFF9CFE2
:200640008091E8008B778093E80008958EB3882349F08091E80080FFF9CF8091E8008E77A4
:200660008093E800089594E68091EC0080FF05C08091E80080FF05C023C08091E80082FD8F
:200680001FC08EB3882311F482E008958EB3853011F483E008958091EB0085FF02C081E0ED
:2006A00008958091E10082FFDFCF8091E1008B7F8093E100992311F484E008959150D4CF46
:2006C00080E008959C0140913602509137024617570718F4F90120E038C06115710511F0B7
:2006E000AB01F8CF8091E8008E778093E80040E050E0F0CF8091E80083FF02C081E0089544
:200700008091E80082FD2DC08EB3882381F18EB3853079F18091E80080FF17C09091F20054
:2007200006C081918093F100415050409F5F4115510511F09830A8F320E0983009F421E0E8
:200740008091E8008E778093E8004115510591F6222381F606C08EB3882349F08EB38530D0
:2007600041F08091E80082FFF6CF80E0089582E0089583E008959C0140913602509137024D
:200780004617570710F490E03BC06115710511F0AB01F9CF8091E8008E778093E80040E0B5
:2007A00050E0F1CF8091E80083FF02C081E008958091E80082FD30C08EB3882399F18EB3EF
:2007C000853091F18091E80080FF1AC08091F20009C0F9012F5F3F4FE491E093F100415044
:2007E00050408F5F4115510511F0883090F390E0883009F491E08091E8008E778093E80004
:200800004115510579F6992369F606C08EB3882349F08EB3853041F08091E80082FFF6CF51
:2008200080E0089582E0089583E008959C016115710529F48091E8008B778093E800F90126
:2008400020C08091E80083FF02C081E008958EB3882339F18EB3853031F18091E80082FFD5
:20086000F0CF06C08091F10081936150704021F08091F2008823B1F78091E8008B77809307
:20088000E80061157105E9F606C08EB3882349F08EB3853041F08091E80080FFF6CF80E0F6
:2008A000089582E0089583E0089542D044D01EBA10922E0210922D0210922C0284E089BD81
:2008C00089B5826089BD09B400FEFDCF8091D800982F9F779093D80080688093D800809186
:2008E00063008E7F809363008091D8008F7D8093D8008091E0008E7F8093E0008091E1004F
:200900008E7F8093E1008091E20081608093E2008091E100877F8093E1008091E200886046
:200920008093E2000895C1DF81E080932F0208951092E20008951092E10008951F920F92B0
:200940000FB60F9211241F932F933F934F935F936F937F938F939F93AF93BF93EF93FF93D2
:20096000E9EEF0E0108117701082E0EFF0E08081877F80837894C3D0F894A9EEB0E01C927D
:20098000E0EFF0E08081886080831C93FF91EF91BF91AF919F918F917F916F915F914F914D
:2009A0003F912F911F910F900FBE0F901F9018951F920F920FB60F9211242F933F934F932D
:2009C0005F936F937F938F939F93AF93BF93EF93FF938091E10080FF1BC08091E20080FF57
:2009E00017C08091E1008E7F8093E1008091E2008E7F8093E2008091E20080618093E2006F
:200A00008091D80080628093D80019BC1EBAD1D18091E10084FF29C08091E20084FF25C018
:200A200084E089BD89B5826089BD09B400FEFDCF8091D8008F7D8093D8008091E1008F7E40
:200A40008093E1008091E2008F7E8093E2008091E20081608093E20080912E02882311F4F3
:200A600081E001C084E08EBBA4D18091E10083FF27C08091E20083FF23C08091E100877F87
:200A80008093E10082E08EBB10922E028091E1008E7F8093E1008091E2008E7F8093E200FD
:200AA0008091E20080618093E200AADD80E060E042E093DD8091F00088608093F00079D17E
:200AC0008091E10082FF0AC08091E20082FF06C08091E1008B7F8093E1006BD1FF91EF9163
:200AE000BF91AF919F918F917F916F915F914F913F912F910F900FBE0F901F9018951F938D
:200B0000DF93CF93CDB7DEB7AC970FB6F894DEBF0FBECDBFE0E3F2E08091F100819322E0B1
:200B2000E833F207C9F78091300230913102353009F487C0363040F43130C9F1313070F08B
:200B4000333009F01DC133C0383009F4EFC0393009F4FEC0363009F013C192C0803821F0E2
:200B6000823809F00DC108C090912C0280912D02882399F0926011C0809134028770809355
:200B8000E9008091EB0090E025E0969587952A95E1F7982F91701092E9008091E800877FCB
:200BA0008093E8009093F1001092F100CAC0882319F0823009F0E4C090E08F7190700097FF
:200BC00021F0029709F0DDC00CC080913202813009F0D7C010922D02333069F580932D02AF
:200BE0002AC080913202882331F520913402277009F4C7C02093E9008091EB0080FFC1C05B
:200C0000333021F48091EB00806213C08091EB0080618093EB0081E090E002C0880F991FEE
:200C20002A95E2F78093EA001092EA008091EB0088608093EB001092E9008091E800877F27
:200C400083C0882309F09CC0109132028091E800877F8093E800E8DC04C08EB3882309F411
:200C600090C08091E80080FFF8CF812F8F7711F492E001C093E09EBB80688093E30081C00C
:200C80008058823008F07CC0809132029091330223E08C3D920799F55FB7F894DE011596DC
:200CA0004EE020E030E061E2E42FF0E060935700849120FF03C082958F704F5F982F9F70F5
:200CC000892F805D8A3308F0895F8C9311961C9211972F5F3F4F12962431310529F75FBF39
:200CE0008AE28B8383E08C838091E800877F8093E800CE0103966AE270E0E4DC11C0609188
:200D00003402AE014F5F5F4F2CDCBC010097C9F18091E800877F8093E80089819A812BDD55
:200D20008091E8008B778093E8002BC0803841F58091E800877F8093E80080912E02809396
:200D4000F1008091E8008E778093E8006DDC19C08823B1F490913202923098F48091E8009B
:200D6000877F8093E80090932E025EDC80912E02882311F483E001C084E08EBBF8DA01C090
:200D8000F3DA8091E80083FF0AC08091EB0080628093EB008091E800877F8093E800AC9629
:200DA0000FB6F894DEBF0FBECDBFCF91DF911F91089508951F938EB3882361F01091E900B9
:200DC0001092E9008091E80083FF01C098DE17701093E9001F9108950895FC018EB38430E7
:200DE00021F587859089A189B2890097A105B105E1F085818093E9008091E80082FF15C03E
:200E00008091F200882319F42FEF3FEF04C08091F100282F30E08091F200882341F48091AA
:200E2000E8008B778093E80002C02FEF3FEFC9010895FC018EB3843011F587859089A18911
:200E4000B2890097A105B105D1F081818093E9008091F2008823A9F09091E8008091E8005C
:200E60008E778093E80095FD0CC0FDDB982F882349F48091E8008E778093E80003C092E05F
:200E800001C090E0892F0895FC018EB3843051F487859089A189B2890097A105B10511F017
:200EA000CF01C7CF08951F93FC01162F8EB38430D9F487859089A189B2890097A105B105FC
:200EC00099F081818093E9008091E80085FD08C08091E8008E778093E800C5DB882329F4E7
:200EE0001093F10080E001C082E01F9108950F931F93CF93DF93EC010D96FC0189E0DF0190
:200F00001D928A95E9F72A813B8109818C81882311F410E001C014E0C90151DB182B126025
:200F2000802F61E8412F59DB882329F12E813F810D818885882311F410E001C014E0C90127
:200F40003EDB182B1260802F60E8412F46DB882391F02A853B8509858C85882311F410E061
:200F600001C014E0C9012BDB182B1260802F61EC412F33DB01C080E0DF91CF911F910F917C
:200F80000895CF93DF93EC018091E80083FF60C0888190E020913402309135022817390781
:200FA00009F056C080913102813261F0823220F4803209F04DC019C0823269F1833209F0C5
:200FC00047C038C080913002813A09F041C08091E800877F8093E800CE010F9667E070E015
:200FE00071DB8091E8008B7713C080913002813279F58091E800877F8093E800CE010F9605
:2010000067E070E013DCCE01E9D88091E8008E778093E8001DC0809130028132C9F4809120
:20102000E800877F8093E800809132028D87CE016ED90DC080913002813251F48091E80057
:20104000877F8093E800CE0160913202C5DEECDADF91CF910895A1E21A2EAA1BBB1BFD0161
:201060000DC0AA1FBB1FEE1FFF1FA217B307E407F50720F0A21BB30BE40BF50B661F771FE6
:20108000881F991F1A9469F760957095809590959B01AC01BD01CF01089597FB092E052647
:2010A0000ED057FD04D0D7DF0AD0001C38F450954095309521953F4F4F4F5F4F0895F6F7B9
:2010C00090958095709561957F4F8F4F9F4F0895F894FFCF000340000004400000020800B9
:0C10E000000000000000000000001400F0
:00000001FF

View File

@@ -1,137 +0,0 @@
:20000000A7C00000C0C00000BEC00000BCC00000BAC00000B8C00000B6C00000B4C0000023
:20002000B2C00000B0C00000AEC00000CBC400008FC40000A8C00000A6C00000A4C000005C
:20004000A2C00000A0C000009EC000009CC000009AC0000098C0000096C0000021C100003A
:2000600092C0000090C000008EC000008CC000008AC0000088C0000086C0000084C0000028
:2000800082C0000080C000007EC000007CC000007AC0000078C000001201100102000008C4
:2000A00041233D0001000102DC0109023E00020100C0320904000001020201000524000143
:2000C00010042402060524060001070582030800FF09040100020A000000070504024000AC
:2000E0000107058302400001040309043203410072006400750069006E006F0020002800CA
:200100007700770077002E00610072006400750069006E006F002E0063006300290000003D
:200120002E03410072006400750069006E006F0020004400750065002000500072006F002D
:2001400067002E00200050006F0072007400000011241FBECFEFD2E0DEBFCDBF11E0A0E029
:20016000B1E0E8EEF0E102C005900D92A831B107D9F712E0A8E1B1E001C01D92A833B107E1
:20018000E1F722D1AFC73CCF9C01DC01AE57BF4FED91FC91119741911196FC93EE93805872
:2001A0009F4FE817F90711F42D933C939FB7F894F901EC57FF4F8081815080839FBF842F6B
:2001C0000895882311F03F9A01C03F9847980895882311F046980895469A0895DF92EF9253
:2001E000FF920F931F93FC018489813019F0823019F404C010E303C010E001C010E283896E
:20020000823009F418608589873031F0883031F0863029F4126003C0146001C016601092A3
:20022000C9001092C8001092CA000785F088E188D288202F3F2D4E2D5D2D10921E01203B7C
:2002400084E0380780E0480780E0580719F481E080931E01CA01B90122E030E040E050E006
:2002600026D720583B47414E5F4FCA01B901202F3F2D4E2D5D2DF9D6215030403093CD00C5
:200280002093CC001093CA0082E08093C80088E98093C9001F910F91FF90EF90DF9008957E
:2002A0001F920F920FB60F9211242F938F939F93EF93FF939091CE008EB38430F1F4E091ED
:2002C000A201F091A3019083E091A201F091A301CF0101969093A3018093A201825A914079
:2002E00021F482E291E0928381839FB7F8948091A6018F5F8093A6019FBFFF91EF919F911B
:200300008F912F910F900FBE0F901F901895FC0140911A0140931B0180911C0180931D015F
:200320008585282F30E02170307020931A01858590E096958795817080931C0180911E013B
:20034000882339F08FE590E090931901809318010895442341F4222331F08EE190E09093DB
:20036000190180931801089580E091E014C680E091E0C7C51F9384B7877F84BF18E10FB69E
:20038000F89410936000109260000FBE80E019DF469A3E9A87E690E09093CD008093CC0043
:2003A00086E08093CA001092C8001093C900539A5A9A8AB180638AB98BB180638BB9BDD2F0
:2003C00084E085BD1F9108950F931F93CF93DF93D1DF2FB7F89487EA91E09093280280939E
:2003E000270290932A02809329022FBF2FB7F89482E291E09093A3018093A2019093A501CC
:200400008093A4012FBF7894C7EAD1E003E08FB7F89490912B028FBF903809F180E091E0E4
:20042000E6D497FD1CC0E0912702F09128028083E0912702F0912802CF0101969093280251
:20044000809327028752924011F4D283C1839FB7F89480912B028F5F80932B029FBF8FB725
:20046000F8941091A6018FBFA89903C0113608F469C0A89A8091A601882361F05D9800936C
:200480001F0108C082E291E07FDE682F80E091E014D511501123B1F780911F01882351F097
:2004A00080911F01815080931F0180911F01882309F45D9A80912001882351F080912001E7
:2004C00081508093200180912001882309F45C9A8091180190911901181619067CF58F3560
:2004E000910521F481E074DE80E06BDE8091180190911901839721F480E06ADE80E061DE1A
:200500008091180190911901499721F480E060DE81E057DE8091180190911901019721F43B
:2005200080E056DE80E04DDE80911801909119010197909319018093180104C080E048DEEC
:2005400080E03FDE8FB7F89490912B028FBF992369F087EA91E018DE982F8091C80085FF9F
:20056000FCCF9093CE005C980093200180E091E095D42AD44CCFDA01923049F0933061F0DA
:200580009130F9F4E8E9F0E022E130E01EC0EAEAF0E02EE330E019C0813049F0813018F0DA
:2005A000823079F408C0E8EEF0E0849107C0ECEEF0E0849103C0E0E2F1E08491282F30E041
:2005C00004C0E0E0F0E020E030E0ED93FC93C901089528E030E040E003C04F5F220F331F15
:2005E00028173907D0F3842F8295807F08958093E9008091EB0081608093EB001092ED00ED
:200600006093EC004093ED008091EE00881F8827881F08951092F40090E09093E9001092EE
:20062000F0001092E8001092ED008091EB008E7F8093EB009F5F953081F70895809130028F
:2006400088238CF403C08EB38823B1F08091E80082FFF9CF8091E8008B778093E80008954A
:200660008EB3882349F08091E80080FFF9CF8091E8008E778093E800089594E68091EC0008
:2006800080FF05C08091E80080FF05C023C08091E80082FD1FC08EB3882311F482E00895AF
:2006A0008EB3853011F483E008958091EB0085FF02C081E008958091E10082FFDFCF8091CD
:2006C000E1008B7F8093E100992311F484E008959150D4CF80E008959C0140913602509171
:2006E00037024617570718F4F90120E038C06115710511F0AB01F8CF8091E8008E77809397
:20070000E80040E050E0F0CF8091E80083FF02C081E008958091E80082FD2DC08EB3882356
:2007200081F18EB3853079F18091E80080FF17C09091F20006C081918093F1004150504088
:200740009F5F4115510511F09830A8F320E0983009F421E08091E8008E778093E800411576
:20076000510591F6222381F606C08EB3882349F08EB3853041F08091E80082FFF6CF80E02F
:20078000089582E0089583E008959C0140913602509137024617570710F490E03BC061155D
:2007A000710511F0AB01F9CF8091E8008E778093E80040E050E0F1CF8091E80083FF02C008
:2007C00081E008958091E80082FD30C08EB3882399F18EB3853091F18091E80080FF1AC073
:2007E0008091F20009C0F9012F5F3F4FE491E093F100415050408F5F4115510511F08830CA
:2008000090F390E0883009F491E08091E8008E778093E8004115510579F6992369F606C0CA
:200820008EB3882349F08EB3853041F08091E80082FFF6CF80E0089582E0089583E0089531
:200840009C016115710529F48091E8008B778093E800F90120C08091E80083FF02C081E084
:2008600008958EB3882339F18EB3853031F18091E80082FFF0CF06C08091F10081936150E7
:20088000704021F08091F2008823B1F78091E8008B778093E80061157105E9F606C08EB379
:2008A000882349F08EB3853041F08091E80080FFF6CF80E0089582E0089583E0089542D0E2
:2008C00044D01EBA10922E0210922D0210922C0284E089BD89B5826089BD09B400FEFDCF22
:2008E0008091D800982F9F779093D80080688093D800809163008E7F809363008091D80084
:200900008F7D8093D8008091E0008E7F8093E0008091E1008E7F8093E1008091E200816028
:200920008093E2008091E100877F8093E1008091E20088608093E2000895C1DF81E0809355
:200940002F0208951092E20008951092E10008951F920F920FB60F9211241F932F933F9355
:200960004F935F936F937F938F939F93AF93BF93EF93FF93E9EEF0E0108117701082E0EF73
:20098000F0E08081877F80837894C3D0F894A9EEB0E01C92E0EFF0E08081886080831C9343
:2009A000FF91EF91BF91AF919F918F917F916F915F914F913F912F911F910F900FBE0F901C
:2009C0001F9018951F920F920FB60F9211242F933F934F935F936F937F938F939F93AF93BC
:2009E000BF93EF93FF938091E10080FF1BC08091E20080FF17C08091E1008E7F8093E10009
:200A00008091E2008E7F8093E2008091E20080618093E2008091D80080628093D80019BC8D
:200A20001EBAD1D18091E10084FF29C08091E20084FF25C084E089BD89B5826089BD09B4B6
:200A400000FEFDCF8091D8008F7D8093D8008091E1008F7E8093E1008091E2008F7E8093E6
:200A6000E2008091E20081608093E20080912E02882311F481E001C084E08EBBA4D1809185
:200A8000E10083FF27C08091E20083FF23C08091E100877F8093E10082E08EBB10922E024B
:200AA0008091E1008E7F8093E1008091E2008E7F8093E2008091E20080618093E200AADDFE
:200AC00080E060E042E093DD8091F00088608093F00079D18091E10082FF0AC08091E2007E
:200AE00082FF06C08091E1008B7F8093E1006BD1FF91EF91BF91AF919F918F917F916F9183
:200B00005F914F913F912F910F900FBE0F901F9018951F93DF93CF93CDB7DEB7AC970FB667
:200B2000F894DEBF0FBECDBFE0E3F2E08091F100819322E0E833F207C9F7809130023091AE
:200B40003102353009F487C0363040F43130C9F1313070F0333009F01DC133C0383009F4B1
:200B6000EFC0393009F4FEC0363009F013C192C0803821F0823809F00DC108C090912C02BC
:200B800080912D02882399F0926011C08091340287708093E9008091EB0090E025E0969548
:200BA00087952A95E1F7982F91701092E9008091E800877F8093E8009093F1001092F1008E
:200BC000CAC0882319F0823009F0E4C090E08F719070009721F0029709F0DDC00CC0809164
:200BE0003202813009F0D7C010922D02333069F580932D022AC080913202882331F52091FB
:200C00003402277009F4C7C02093E9008091EB0080FFC1C0333021F48091EB00806213C0C2
:200C20008091EB0080618093EB0081E090E002C0880F991F2A95E2F78093EA001092EA00D6
:200C40008091EB0088608093EB001092E9008091E800877F83C0882309F09CC01091320210
:200C60008091E800877F8093E800E8DC04C08EB3882309F490C08091E80080FFF8CF812FCA
:200C80008F7711F492E001C093E09EBB80688093E30081C08058823008F07CC08091320228
:200CA0009091330223E08C3D920799F55FB7F894DE0115964EE020E030E061E2E42FF0E05B
:200CC00060935700849120FF03C082958F704F5F982F9F70892F805D8A3308F0895F8C93E8
:200CE00011961C9211972F5F3F4F12962431310529F75FBF8AE28B8383E08C838091E80085
:200D0000877F8093E800CE0103966AE270E0E4DC11C060913402AE014F5F5F4F2CDCBC0146
:200D20000097C9F18091E800877F8093E80089819A812BDD8091E8008B778093E8002BC05A
:200D4000803841F58091E800877F8093E80080912E028093F1008091E8008E778093E8006D
:200D60006DDC19C08823B1F490913202923098F48091E800877F8093E80090932E025EDCD7
:200D800080912E02882311F483E001C084E08EBBEEDA01C0E9DA8091E80083FF0AC08091EF
:200DA000EB0080628093EB008091E800877F8093E800AC960FB6F894DEBF0FBECDBFCF9185
:200DC000DF911F91089508951F938EB3882361F01091E9001092E9008091E80083FF01C079
:200DE00098DE17701093E9001F9108950895FC018EB3843021F587859089A189B289009757
:200E0000A105B105E1F085818093E9008091E80082FF15C08091F200882319F42FEF3FEF4D
:200E200004C08091F100282F30E08091F200882341F48091E8008B778093E80002C02FEFCC
:200E40003FEFC9010895FC018EB3843011F587859089A189B2890097A105B105D1F08181C5
:200E60008093E9008091F2008823A9F09091E8008091E8008E778093E80095FD0CC0FDDBF7
:200E8000982F882349F48091E8008E778093E80003C092E001C090E0892F0895FC018EB3B1
:200EA000843051F487859089A189B2890097A105B10511F0CF01C7CF08951F93FC01162FC4
:200EC0008EB38430D9F487859089A189B2890097A105B10599F081818093E9008091E80053
:200EE00085FD08C08091E8008E778093E800C5DB882329F41093F10080E001C082E01F9180
:200F000008950F931F93CF93DF93EC010D96FC0189E0DF011D928A95E9F72A813B81098197
:200F20008C81882311F410E001C014E0C90151DB182B1260802F61E8412F59DB882329F143
:200F40002E813F810D818885882311F410E001C014E0C9013EDB182B1260802F60E8412F33
:200F600046DB882391F02A853B8509858C85882311F410E001C014E0C9012BDB182B12603C
:200F8000802F61EC412F33DB01C080E0DF91CF911F910F910895CF93DF93EC018091E8003F
:200FA00083FF60C0888190E020913402309135022817390709F056C080913102813261F061
:200FC000823220F4803209F04DC019C0823269F1833209F047C038C080913002813A09F006
:200FE00041C08091E800877F8093E800CE010F9667E070E071DB8091E8008B7713C08091C0
:201000003002813279F58091E800877F8093E800CE010F9667E070E013DCCE01DFD88091F2
:20102000E8008E778093E8001DC0809130028132C9F48091E800877F8093E80080913202F9
:201040008D87CE0164D90DC080913002813251F48091E800877F8093E800CE01609132027A
:20106000C5DEECDADF91CF910895A1E21A2EAA1BBB1BFD010DC0AA1FBB1FEE1FFF1FA217E2
:20108000B307E407F50720F0A21BB30BE40BF50B661F771F881F991F1A9469F760957095B3
:2010A000809590959B01AC01BD01CF01089597FB092E05260ED057FD04D0D7DF0AD0001CDC
:2010C00038F450954095309521953F4F4F4F5F4F0895F6F790958095709561957F4F8F4F6A
:2010E0009F4F0895F894FFCF00034000000440000002080000000000000000000000140066
:00000001FF

View File

@@ -1,273 +0,0 @@
:10000000A7C00000C0C00000BEC00000BCC000000F
:10001000BAC00000B8C00000B6C00000B4C0000004
:10002000B2C00000B0C00000AEC00000C1C40000FB
:1000300085C40000A8C00000A6C00000A4C0000045
:10004000A2C00000A0C000009EC000009CC0000034
:100050009AC0000098C0000096C0000021C10000B6
:1000600092C0000090C000008EC000008CC0000054
:100070008AC0000088C0000086C0000084C0000064
:1000800082C0000080C000007EC000007CC0000074
:100090007AC0000078C000001201100102000008C0
:1000A00041233D0001000102DC0109023E00020182
:1000B00000C0320904000001020201000524000111
:1000C0001004240206052406000107058203080027
:1000D000FF09040100020A000000070504024000B5
:1000E00001070583024000010403090432034100B3
:1000F00072006400750069006E006F002000280027
:100100007700770077002E006100720064007500B0
:1001100069006E006F002E0063006300290000007C
:100120002E03410072006400750069006E006F00CC
:1001300020004400750065002000500072006F0030
:1001400067002E00200050006F0072007400000055
:1001500011241FBECFEFD2E0DEBFCDBF11E0A0E083
:10016000B1E0E4EDF0E102C005900D92A831B107D5
:10017000D9F712E0A8E1B1E001C01D92A833B107A0
:10018000E1F72BD1A5C73CCF9C01DC01AE57BF4F97
:10019000ED91FC91119741911196FC93EE9380584B
:1001A0009F4FE817F90711F42D933C939FB7F894EC
:1001B000F901EC57FF4F8081815080839FBF842FCE
:1001C0000895882311F03F9A01C03F9847980895F9
:1001D000882311F046980895469A0895DF92EF9289
:1001E000FF920F931F93FC018489813019F08230B4
:1001F00019F404C010E303C010E001C010E28389C9
:10020000823009F418608589873031F0883031F008
:10021000863029F4126003C0146001C01660109289
:10022000C9001092C8001092CA000785F088E188C2
:10023000D288202F3F2D4E2D5D2D10921E01203B88
:1002400084E0380780E0480780E0580719F481E02F
:1002500080931E01CA01B90122E030E040E050E085
:100260001CD720583B47414E5F4FCA01B901202F90
:100270003F2D4E2D5D2DEFD6215030403093CD00D7
:100280002093CC001093CA0082E08093C80088E9D4
:100290008093C9001F910F91FF90EF90DF90089518
:1002A0001F920F920FB60F9211242F938F939F934B
:1002B000EF93FF939091CE008EB38430F1F4E091F0
:1002C000A201F091A3019083E091A201F091A3011A
:1002D000CF0101969093A3018093A201825A91408D
:1002E00021F482E291E0928381839FB7F894809118
:1002F000A6018F5F8093A6019FBFFF91EF919F9111
:100300008F912F910F900FBE0F901F901895FC01A9
:1003100040911A0140931B0180911C0180931D01A3
:100320008585282F30E02170307020931A01858553
:1003300090E096958795817080931C0180911E01B5
:10034000882339F088E790E0909319018093180191
:100350000895442341F4222331F082E390E0909306
:10036000190180931801089580E091E00AC680E0A9
:1003700091E0BDC584B7877F84BF88E10FB6F8944C
:1003800080936000109260000FBE81E01ADF16BCFF
:1003900083E085BD86B58831E8F315BC16BC80E0E6
:1003A00010DF469A3E9A87E690E09093CD008093C6
:1003B000CC0086E08093CA001092C80088E1809348
:1003C000C900539A5A9A8AB180638AB98BB1806303
:1003D0008BB9A9D284E085BD08950F931F93CF9365
:1003E000DF93C8DF2FB7F89487EA91E09093280253
:1003F0008093270290932A02809329022FBF2FB760
:10040000F89482E291E09093A3018093A2019093EB
:10041000A5018093A4012FBF7894C7EAD1E003E03F
:100420008FB7F89490912B028FBF903809F180E03C
:1004300091E0D3D497FD1CC0E0912702F0912802EF
:100440008083E0912702F0912802CF0101969093DA
:100450002802809327028752924011F4D283C183ED
:100460009FB7F89480912B028F5F80932B029FBFE0
:100470008FB7F8941091A6018FBFA89903C01136C9
:1004800008F456C0A89A8091A601882361F05D986F
:1004900000931F0108C082E291E076DE682F80E0C1
:1004A00091E001D511501123B1F780911F018823EC
:1004B00051F080911F01815080931F0180911F0195
:1004C000882309F45D9A80912001882351F080915E
:1004D000200181508093200180912001882309F41C
:1004E0005C9A809118019091190118161906E4F48C
:1004F000CC97CD9710F481E001C080E069DE809157
:100500001801909119010197C29710F481E001C080
:1005100080E057DE80911801909119010197909326
:1005200019018093180104C080E052DE80E049DEAA
:100530008FB7F89490912B028FBF992369F087EAC7
:1005400091E022DE982F8091C80085FFFCCF909328
:10055000CE005C980093200180E091E095D42AD4ED
:100560005FCFDA01923049F0933061F09130F9F4C5
:10057000E8E9F0E022E130E01EC0EAEAF0E02EE334
:1005800030E019C0813049F0813018F0823079F4C0
:1005900008C0E8EEF0E0849107C0ECEEF0E0849152
:1005A00003C0E0E2F1E08491282F30E004C0E0E0F5
:1005B000F0E020E030E0ED93FC93C901089528E0DD
:1005C00030E040E003C04F5F220F331F2817390788
:1005D000D0F3842F8295807F08958093E9008091E5
:1005E000EB0081608093EB001092ED006093EC00D3
:1005F0004093ED008091EE00881F8827881F0895A2
:100600001092F40090E09093E9001092F0001092A4
:10061000E8001092ED008091EB008E7F8093EB005C
:100620009F5F953081F708958091300288238CF484
:1006300003C08EB38823B1F08091E80082FFF9CF28
:100640008091E8008B778093E80008958EB388232B
:1006500049F08091E80080FFF9CF8091E8008E7723
:100660008093E800089594E68091EC0080FF05C037
:100670008091E80080FF05C023C08091E80082FDE2
:100680001FC08EB3882311F482E008958EB38530A5
:1006900011F483E008958091EB0085FF02C081E0B2
:1006A00008958091E10082FFDFCF8091E1008B7F90
:1006B0008093E100992311F484E008959150D4CF00
:1006C00080E008959C014091360250913702461710
:1006D000570718F4F90120E038C06115710511F0D1
:1006E000AB01F8CF8091E8008E778093E80040E07E
:1006F00050E0F0CF8091E80083FF02C081E00895D0
:100700008091E80082FD2DC08EB3882381F18EB3E5
:10071000853079F18091E80080FF17C09091F20058
:1007200006C081918093F100415050409F5F411578
:10073000510511F09830A8F320E0983009F421E039
:100740008091E8008E778093E8004115510591F67D
:10075000222381F606C08EB3882349F08EB38530FC
:1007600041F08091E80082FFF6CF80E0089582E0BA
:10077000089583E008959C0140913602509137021C
:100780004617570710F490E03BC06115710511F052
:10079000AB01F9CF8091E8008E778093E80040E0CC
:1007A00050E0F1CF8091E80083FF02C081E008951E
:1007B0008091E80082FD30C08EB3882399F18EB31A
:1007C000853091F18091E80080FF1AC08091F2009D
:1007D00009C0F9012F5F3F4FE491E093F1004150D0
:1007E00050408F5F4115510511F0883090F390E033
:1007F000883009F491E08091E8008E778093E800DA
:100800004115510579F6992369F606C08EB3882300
:1008100049F08EB3853041F08091E80082FFF6CF39
:1008200080E0089582E0089583E008959C016115B9
:10083000710529F48091E8008B778093E800F90135
:1008400020C08091E80083FF02C081E008958EB34C
:10085000882339F18EB3853031F18091E80082FF31
:10086000F0CF06C08091F10081936150704021F07B
:100870008091F2008823B1F78091E8008B77809314
:10088000E80061157105E9F606C08EB3882349F0CA
:100890008EB3853041F08091E80080FFF6CF80E094
:1008A000089582E0089583E0089542D044D01EBAAE
:1008B00010922E0210922D0210922C0284E089BD1B
:1008C00089B5826089BD09B400FEFDCF8091D80052
:1008D000982F9F779093D80080688093D80080915C
:1008E00063008E7F809363008091D8008F7D80931A
:1008F000D8008091E0008E7F8093E0008091E1003D
:100900008E7F8093E1008091E20081608093E2001D
:100910008091E100877F8093E1008091E200886010
:100920008093E2000895C1DF81E080932F02089553
:100930001092E20008951092E10008951F920F9224
:100940000FB60F9211241F932F933F934F935F93F2
:100950006F937F938F939F93AF93BF93EF93FF9387
:10096000E9EEF0E0108117701082E0EFF0E0808196
:10097000877F80837894C3D0F894A9EEB0E01C926E
:10098000E0EFF0E08081886080831C93FF91EF911D
:10099000BF91AF919F918F917F916F915F914F9197
:1009A0003F912F911F910F900FBE0F901F901895A0
:1009B0001F920F920FB60F9211242F933F934F93D4
:1009C0005F936F937F938F939F93AF93BF93EF93B7
:1009D000FF938091E10080FF1BC08091E20080FFC7
:1009E00017C08091E1008E7F8093E1008091E2004A
:1009F0008E7F8093E2008091E20080618093E2002C
:100A00008091D80080628093D80019BC1EBAD1D1E1
:100A10008091E10084FF29C08091E20084FF25C01D
:100A200084E089BD89B5826089BD09B400FEFDCF2F
:100A30008091D8008F7D8093D8008091E1008F7ED7
:100A40008093E1008091E2008F7E8093E2008091AC
:100A5000E20081608093E20080912E02882311F4ED
:100A600081E001C084E08EBBA4D18091E10083FFCE
:100A700027C08091E20083FF23C08091E100877F3F
:100A80008093E10082E08EBB10922E028091E10003
:100A90008E7F8093E1008091E2008E7F8093E20060
:100AA0008091E20080618093E200AADD80E060E056
:100AB00042E093DD8091F00088608093F00079D16E
:100AC0008091E10082FF0AC08091E20082FF06C0AF
:100AD0008091E1008B7F8093E1006BD1FF91EF91DA
:100AE000BF91AF919F918F917F916F915F914F9146
:100AF0003F912F910F900FBE0F901F9018951F934D
:100B0000DF93CF93CDB7DEB7AC970FB6F894DEBFC7
:100B10000FBECDBFE0E3F2E08091F100819322E0CF
:100B2000E833F207C9F78091300230913102353055
:100B300009F487C0363040F43130C9F1313070F0FB
:100B4000333009F01DC133C0383009F4EFC03930FB
:100B500009F4FEC0363009F013C192C0803821F08C
:100B6000823809F00DC108C090912C0280912D02AD
:100B7000882399F0926011C080913402877080932D
:100B8000E9008091EB0090E025E0969587952A9505
:100B9000E1F7982F91701092E9008091E800877F2B
:100BA0008093E8009093F1001092F100CAC088236E
:100BB00019F0823009F0E4C090E08F7190700097D6
:100BC00021F0029709F0DDC00CC080913202813023
:100BD00009F0D7C010922D02333069F580932D02B1
:100BE0002AC080913202882331F520913402277087
:100BF00009F4C7C02093E9008091EB0080FFC1C0D9
:100C0000333021F48091EB00806213C08091EB00BF
:100C100080618093EB0081E090E002C0880F991F13
:100C20002A95E2F78093EA001092EA008091EB00A7
:100C300088608093EB001092E9008091E800877F44
:100C400083C0882309F09CC0109132028091E80093
:100C5000877F8093E800E8DC04C08EB3882309F422
:100C600090C08091E80080FFF8CF812F8F7711F43A
:100C700092E001C093E09EBB80688093E30081C056
:100C80008058823008F07CC080913202909133020B
:100C900023E08C3D920799F55FB7F894DE01159635
:100CA0004EE020E030E061E2E42FF0E06093570096
:100CB000849120FF03C082958F704F5F982F9F70A3
:100CC000892F805D8A3308F0895F8C9311961C927E
:100CD00011972F5F3F4F12962431310529F75FBFDF
:100CE0008AE28B8383E08C838091E800877F809306
:100CF000E800CE0103966AE270E0E4DC11C0609186
:100D00003402AE014F5F5F4F2CDCBC010097C9F18C
:100D10008091E800877F8093E80089819A812BDDAC
:100D20008091E8008B778093E8002BC0803841F5F4
:100D30008091E800877F8093E80080912E02809365
:100D4000F1008091E8008E778093E8006DDC19C097
:100D50008823B1F490913202923098F48091E800A7
:100D6000877F8093E80090932E025EDC80912E02B4
:100D7000882311F483E001C084E08EBBF8DA01C05F
:100D8000F3DA8091E80083FF0AC08091EB00806273
:100D90008093EB008091E800877F8093E800AC9619
:100DA0000FB6F894DEBF0FBECDBFCF91DF911F917C
:100DB000089508951F938EB3882361F01091E90080
:100DC0001092E9008091E80083FF01C098DE17705F
:100DD0001093E9001F9108950895FC018EB38430AB
:100DE00021F587859089A189B2890097A105B10570
:100DF000E1F085818093E9008091E80082FF15C0D1
:100E00008091F200882319F42FEF3FEF04C0809106
:100E1000F100282F30E08091F200882341F4809186
:100E2000E8008B778093E80002C02FEF3FEFC90105
:100E30000895FC018EB3843011F587859089A189CE
:100E4000B2890097A105B105D1F081818093E900B5
:100E50008091F2008823A9F09091E8008091E80049
:100E60008E778093E80095FD0CC0FDDB982F8823DA
:100E700049F48091E8008E778093E80003C092E007
:100E800001C090E0892F0895FC018EB3843051F4A5
:100E900087859089A189B2890097A105B10511F0D4
:100EA000CF01C7CF08951F93FC01162F8EB3843056
:100EB000D9F487859089A189B2890097A105B105E8
:100EC00099F081818093E9008091E80085FD08C058
:100ED0008091E8008E778093E800C5DB882329F4B1
:100EE0001093F10080E001C082E01F9108950F93FC
:100EF0001F93CF93DF93EC010D96FC0189E0DF0196
:100F00001D928A95E9F72A813B8109818C8188238A
:100F100011F410E001C014E0C90151DB182B12607C
:100F2000802F61E8412F59DB882329F12E813F81F1
:100F30000D818885882311F410E001C014E0C901F7
:100F40003EDB182B1260802F60E8412F46DB8823A0
:100F500091F02A853B8509858C85882311F410E062
:100F600001C014E0C9012BDB182B1260802F61EC4B
:100F7000412F33DB01C080E0DF91CF911F910F91B2
:100F80000895CF93DF93EC018091E80083FF60C068
:100F9000888190E02091340230913502281739077A
:100FA00009F056C080913102813261F0823220F422
:100FB000803209F04DC019C0823269F1833209F0E4
:100FC00047C038C080913002813A09F041C0809119
:100FD000E800877F8093E800CE010F9667E070E01D
:100FE00071DB8091E8008B7713C0809130028132F1
:100FF00079F58091E800877F8093E800CE010F9615
:1010000067E070E013DCCE01E9D88091E8008E77CC
:101010008093E8001DC0809130028132C9F4809134
:10102000E800877F8093E800809132028D87CE01AF
:101030006ED90DC080913002813251F48091E80068
:10104000877F8093E800CE0160913202C5DEECDA42
:10105000DF91CF910895A1E21A2EAA1BBB1BFD01BF
:101060000DC0AA1FBB1FEE1FFF1FA217B307E40787
:10107000F50720F0A21BB30BE40BF50B661F771FDF
:10108000881F991F1A9469F76095709580959095BF
:101090009B01AC01BD01CF01089597FB092E0526E8
:1010A0000ED057FD04D0D7DF0AD0001C38F450957D
:1010B0004095309521953F4F4F4F5F4F0895F6F77C
:1010C00090958095709561957F4F8F4F9F4F0895B4
:0410D000F894FFCFC2
:1010D400000340000004400000020800000000007B
:0810E4000000000000001400F0
:00000001FF

View File

@@ -0,0 +1,277 @@
:100000009FC00000B8C00000B6C00000B4C000002F
:10001000B2C00000B0C00000AEC00000ACC0000024
:10002000AAC00000A8C00000A6C00000B5C3000020
:100030005AC40000A0C000009EC000009CC0000088
:100040009AC0000098C0000096C0000094C0000054
:1000500092C0000090C000008EC0000007C20000E7
:100060008AC0000088C0000086C0000084C0000074
:1000700082C00000D704F904EB05F904EB053E0546
:100080005B05EB05AE05C0052E0341007200640060
:10009000750069006E006F00200044007500650067
:1000A0002000500072006F0067002E0020005000FA
:1000B0006F0072007400000032034100720064009F
:1000C000750069006E006F0020002800770077003F
:1000D00077002E00610072006400750069006E00F8
:1000E0006F002E0063006300290000000403090470
:1000F00009023E00020100C03209040000010202B0
:100100000100052400011004240206052406000154
:10011000070582030800FF09040100020A0000002D
:100120000705040240000107058302400001120197
:1001300010010200000841233D0001000102DC0122
:1001400011241FBECFEFD2E0DEBFCDBF11E0A0E093
:10015000B1E0EEE1F1E102C005900D92AA31B107E4
:10016000D9F722E0AAE1B1E001C01D92A833B2079D
:10017000E1F77BD0D2C744CFFC01E058FF4FA0810C
:10018000B1816C93A081B1819D012F5F3F4F31837D
:1001900020832E173F0721F412969C938E9311977C
:1001A0002FB7F894FC01EC57FF4F80818F5F80835D
:1001B0002FBF0895DC01AE57BF4FED91FC91119711
:1001C00021911196FC93EE93AC0140585F4FE417D8
:1001D000F50711F48D939C933FB7F894FC01EC570D
:1001E000FF4F9081915090833FBF822F08958823C5
:1001F00021F03F9A47985C9808953F9847985C9AF9
:100200000895882319F046985D980895469A5D9A56
:10021000089584B7877F84BF0FB6F894A89580911E
:100220006000886180936000109260000FBE80E0E3
:10023000DEDF469A3E9A87E690E09093CD00809369
:10024000CC0086E08093CA001092C80088E18093B9
:10025000C900539A5A9A8AB180638AB98BB1806374
:100260008BB98FD284E085BD0895D3DF2FB7F89482
:1002700087EA91E0909328028093270290932A02C4
:10028000809329022FBF2FB7F89482E291E09093D8
:10029000A3018093A2019093A5018093A4012FBF95
:1002A0007894D3E09FB7F89480912B029FBF803859
:1002B00049F084E091E0C2D697FD04C0682F87EA38
:1002C00091E05ADF8FB7F894C091A6018FBFA8992B
:1002D00003C0C13608F453C0A89A8091A6018823B0
:1002E00019F05D98D0931F01CC2349F082E291E090
:1002F00061DF682F84E091E042D6C150F5CF809154
:100300001F01882341F080911F01815080931F01BC
:10031000811101C05D9A80912001882341F0809174
:100320002001815080932001811101C05C9A80914D
:1003300002019091030118161906ECF4CC97853B45
:10034000910510F481E001C080E05BDF8091020143
:10035000909103010197C29710F481E001C080E001
:1003600046DF809102019091030101979093030170
:100370008093020104C080E044DF80E038DF9FB753
:10038000F89480912B029FBF882361F087EA91E067
:1003900011DF9091C80095FFFCCF8093CE005C9850
:1003A000D093200184E091E03BD608D57BCF84E058
:1003B00091E086C584E091E013C5CF92DF92EF9281
:1003C000FF92CF93FC018489813021F0823021F4A7
:1003D000C0E203C0C0E301C0C0E08389823009F4F9
:1003E000C8608589873031F0883031F0863029F453
:1003F000C26003C0C46001C0C6601092C900109200
:10040000C8001092CA00C784D088E188F28881E0D1
:1004100090EBC91694E0D906E104F10409F080E0FC
:1004200080931A01C701B60122E030E040E050E0BD
:1004300052D6CA01B90160587B47814E9F4FA70130
:10044000960127D6215031093093CD002093CC005E
:10045000C093CA0082E08093C80088E98093C900F5
:10046000CF91FF90EF90DF90CF9008951F920F9261
:100470000FB60F9211242F933F934F935F936F9377
:100480007F938F939F93AF93BF93EF93FF9360916D
:10049000CE008EB3843019F482E291E06DDEFF91DC
:1004A000EF91BF91AF919F918F917F916F915F91EC
:1004B0004F913F912F910F900FBE0F901F90189565
:1004C00020911E0120931D0130911C0130931B01CE
:1004D000FC018585982F917090931E0186958170FF
:1004E00080931C0180911A01882319F084EB90E01D
:1004F00006C0211108C0992331F082E390E0909367
:100500000301809302010895292F332722303105FA
:1005100059F02330310569F021303105E9F482E1E9
:1005200090E02EE231E01CC08EE390E020EF30E05E
:1005300017C099278130910549F028F0029761F49E
:10054000E8E8F0E005C0ECEEF0E002C0E8EBF0E037
:10055000849190E09F0104C080E090E020E030E0D2
:10056000FA01318320830895EF92FF920F931F9336
:10057000CF93DF93CDB7DEB72A970FB6F894DEBFDF
:100580000FBECDBF7E0126E0E20EF11CFE013196CA
:100590009F01870190E09093E9005091EC00D80111
:1005A0005D938D015091ED00D9015D939D019F5F99
:1005B000953089F7282F30E08701020F131FD801EB
:1005C0006C932E0F3F1FD9014C9391E09093E9005B
:1005D0001092F0001092E8001092ED002091EB00D4
:1005E0002E7F2093EB009F5F953081F790E0208174
:1005F00021FD0BC09F5F3196BFEFEB1AFB0A9530D0
:10060000B1F78093E90081E013C09093E900209155
:10061000EB0021602093EB00D7012C912093EC009C
:1006200020812093ED002091EE0027FDE3CF80E0B4
:100630002A960FB6F894DEBF0FBECDBFDF91CF91E3
:100640001F910F91FF90EF9008951092F40080E0B9
:100650008093E9001092F0001092E8001092ED00F3
:100660009091EB009E7F9093EB008F5F853081F738
:1006700008958091300287FF0FC08091E80082FDCD
:1006800004C08EB38111F9CF10C08091E8008B7740
:100690000AC08EB3882349F08091E80080FFF9CF2B
:1006A0008091E8008E778093E800089585E6909128
:1006B000EC0090FF05C09091E80090FF05C01BC0C2
:1006C0009091E80092FD17C09EB39923B1F09EB3BC
:1006D0009530A9F09091EB0095FD13C09091E10049
:1006E00092FFE5CF9091E1009B7F9093E1008150D4
:1006F000F1F684E0089580E0089582E0089583E0B3
:10070000089581E0089542D044D01EBA10922E027E
:1007100010922D0210922C0284E089BD89B582606E
:1007200089BD09B400FEFDCF8091D800982F9F7736
:100730009093D80080688093D800809163008E7F6A
:10074000809363008091D8008F7D8093D800809142
:10075000E0008E7F8093E0008091E1008E7F8093A7
:10076000E1008091E20081608093E2008091E100ED
:10077000877F8093E1008091E20088608093E200AF
:100780000895C1DF81E080932F0208951092E20066
:1007900008951092E10008951F920F920FB60F92E4
:1007A00011242F933F934F935F936F937F938F9376
:1007B0009F93AF93BF93EF93FF938091E10080FFEE
:1007C0001BC08091E20080FF17C08091E1008E7F06
:1007D0008093E1008091E2008E7F8093E20080911F
:1007E000E20080618093E2008091D8008062809373
:1007F000D80019BC1EBAFBD18091E10084FF29C04A
:100800008091E20084FF25C084E089BD89B58260C3
:1008100089BD09B400FEFDCF8091D8008F7D809303
:10082000D8008091E1008F7E8093E1008091E2000A
:100830008F7E8093E2008091E20081608093E200ED
:1008400080912E02811102C081E001C084E08EBB44
:10085000CED18091E10083FF27C08091E20083FF29
:1008600023C08091E100877F8093E10082E08EBB0E
:1008700010922E028091E1008E7F8093E1008091A2
:10088000E2008E7F8093E2008091E200806180939D
:10089000E200DBDE42E060E080E066DE8091F000B6
:1008A00088608093F000A3D18091E10082FF0AC0AC
:1008B0008091E20082FF06C08091E1008B7F8093EF
:1008C000E10095D1FF91EF91BF91AF919F918F91F1
:1008D0007F916F915F914F913F912F910F900FBE3C
:1008E0000F901F9018951F920F920FB60F92112420
:1008F000FF920F931F932F933F934F935F936F93A9
:100900007F938F939F93AF93BF93CF93DF93EF9397
:10091000FF93C9EED0E088818770F82E188200EF2F
:1009200010E0F8018081877F808378941DD0F8944F
:100930001882F801808188608083F882FF91EF91AE
:10094000DF91CF91BF91AF919F918F917F916F91E7
:100950005F914F913F912F911F910F91FF900F90B9
:100960000FBE0F901F9018951F93CF93DF93CDB7B5
:10097000DEB7AA970FB6F894DEBF0FBECDBFE0E397
:10098000F2E088E392E02091F10021938E179F0717
:10099000D1F78091300290913102492F50E04A30D6
:1009A000510508F018C1FA01E65CFF4FB0C380386A
:1009B00081F0823809F00FC18091340287708093F2
:1009C000E9008091EB0085FB882780F91092E9000F
:1009D00006C080912C0290912D029111826090911D
:1009E000E800977F9093E8008093F1001092F10067
:1009F000C0C0282F2D7F09F0EEC0882319F0823067
:100A000061F0DAC080913202813009F0D5C09330B4
:100A100009F080E080932D022BC080913202811179
:100A200027C080913402877009F4C6C08093E90022
:100A30002091EB0020FFC0C0933021F48091EB00A7
:100A4000806214C09091EB0090619093EB0021E0E4
:100A500030E0A90102C0440F551F8A95E2F7409388
:100A6000EA001092EA008091EB0088608093EB002E
:100A70001092E9008091E800877F7EC08111ABC0B1
:100A8000109132028091E800877F8093E800F1DDC9
:100A90008091E80080FD04C08EB38111F9CF8CC035
:100AA000812F8F7711F492E001C093E09EBB8068A4
:100AB0008093E30081C08058823008F08CC0809120
:100AC0003202909133028C3D53E0950779F583E033
:100AD0008A838AE289833FB7F894DE01139690E017
:100AE0002EE041E2E22FF0E040935700E49190FFC6
:100AF00003C0E295EF702F5FEF7080E38E0F8A33B3
:100B000010F0E95C01C0E82FF0E0ED93FD939F5FEA
:100B1000943141F73FBF8091E800877F8093E800E0
:100B20006AE270E0CE01019663D012C0AE014F5F61
:100B30005F4F60913402E8DCBC01892B09F43CC0B2
:100B40009091E800977F9093E80089819A81A6D0E0
:100B50008091E8008B778093E8002EC08038D9F52B
:100B60008091E800877F8093E80080912E02809337
:100B7000F1008091E8008E778093E8007ADD1CC058
:100B8000811129C0809132029091330299270297F6
:100B90009CF48091E800877F8093E8008091320286
:100BA00080932E0266DD80912E02811102C083E0C7
:100BB00001C084E08EBBFBDB8091E80083FF0DC0A9
:100BC0008091EB0080628093EB008091E800877F4A
:100BD0008093E80002C0EEDBEFCFAA960FB6F89440
:100BE000DEBF0FBECDBFDF91CF911F910895089555
:100BF00020913602309137022617370748F06115E9
:100C0000710539F42091E8002E772093E80001C0A7
:100C1000B90130E06115710561F12091E80023FD13
:100C200037C02091E80022FD2DC02EB3222391F180
:100C30002EB3253089F12091E80020FFEBCF2091E1
:100C4000F200FC01CF016115710549F0283038F43C
:100C500081918093F100615071092F5FF3CF31E0F2
:100C6000283009F030E02091E8002E772093E8004A
:100C7000D1CF3111D2CF06C08EB3882359F08EB3B5
:100C8000853051F08091E80082FFF6CF80E0089532
:100C900081E0089582E0089583E00895209136026E
:100CA000309137022617370748F06115710539F47E
:100CB0002091E8002E772093E80001C0B90130E0D0
:100CC0006115710569F12091E80023FD38C020917C
:100CD000E80022FD2EC02EB3222399F12EB3253039
:100CE00091F12091E80020FFEBCF2091F200FC0170
:100CF000CF016115710551F0283040F48491809343
:100D0000F100615071092F5F3196F2CF31E0283048
:100D100009F030E02091E8002E772093E800D0CF52
:100D20003111D1CF06C08EB3882359F08EB38530F0
:100D300051F08091E80082FFF6CF80E0089581E0D5
:100D4000089582E0089583E008956115710529F4FE
:100D50002091E8002B772093E8006115710511F1CF
:100D60002091E80023FD24C02EB3222319F12EB3D5
:100D7000253011F12091E80022FFEFCF2091F20001
:100D8000222331F301962091F100FC013197208359
:100D90006150710999F7DCCF8EB3882359F08EB377
:100DA000853051F08091E80080FFF6CF80E0089513
:100DB00081E0089582E0089583E00895CF938EB393
:100DC000882359F0C091E900C7701092E900809122
:100DD000E80083FDC9DDC093E900CF91089508952F
:100DE000CF93DF932091E80023FF67C0FC012081AF
:100DF00030E040913402509135024217530709F018
:100E00005CC0EC0180913102813251F018F48032E3
:100E1000E1F053C0823281F1833209F43EC04DC00B
:100E200080913002813A09F048C08091E800877FC4
:100E30008093E80067E070E0CF010F96D9DE8091E3
:100E4000E8008B778093E80038C0809130028132CF
:100E5000A1F58091E800877F8093E80067E070E06B
:100E6000CF010F9672DF8091E8008E778093E800C3
:100E7000CE01DF91CF91A1CA809130028132E9F495
:100E80008091E800877F8093E800F3DB8091320255
:100E90008D87CE01DF91CF9113CB809130028132CB
:100EA00061F48091E800877F8093E800E2DB609145
:100EB0003202CE01DF91CF9192CFDF91CF91089591
:100EC000CF93DF93EC01FC013D9689E0DF011D9299
:100ED0008A95E9F78C81811102C090E001C094E00D
:100EE0006A817B81898128E030E040E0261737075E
:100EF00020F44F5F220F331FF9CF4295407F92605D
:100F0000492B61E831DB8823B1F18885811102C06A
:100F100090E001C094E06E817F818D8128E030E017
:100F200040E02617370720F44F5F220F331FF9CF19
:100F30004295407F9260492B60E816DB8823D9F008
:100F40008C85811102C090E001C094E06A857B85A8
:100F5000898528E030E040E02617370720F44F5F0E
:100F6000220F331FF9CF4295407F9260492B61ECED
:100F7000DF91CF91F9CA80E0DF91CF9108950F936F
:100F80001F93CF932EB32430F1F4FC010785108911
:100F900021893289012B022B032BA9F0C62F8181D5
:100FA0008093E9008091E80085FF04C0C093F100C0
:100FB00080E00AC08091E8008E778093E80076DBBD
:100FC0008823A1F301C082E0CF911F910F91089572
:100FD0002EB3243019F5FC01478550896189728947
:100FE000452B462B472BD1F081818093E9008091DE
:100FF000F200882389F09091E8008091E8008E77D4
:101000008093E80095FD08C051DB811108C08091F4
:10101000E8008E778093E80080E0089582E00895EC
:101020002EB3243051F4FC014785508961897289BF
:10103000452B462B472B09F0CBCF08952EB32430F8
:1010400019F08FEF9FEF0895FC0147855089618962
:101050007289452B462B472BA1F385818093E900AC
:101060008091E80082FFEDCF8091F200882321F08B
:101070002091F10030E002C02FEF3FEF8091F200AD
:10108000811105C08091E8008B778093E800C90149
:101090000895A1E21A2EAA1BBB1BFD010DC0AA1FB9
:1010A000BB1FEE1FFF1FA217B307E407F50720F0D1
:1010B000A21BB30BE40BF50B661F771F881F991F4C
:1010C0001A9469F760957095809590959B01AC0195
:1010D000BD01CF010895052E97FB16F400940FD0A3
:1010E00057FD05D0D6DF07FC02D046F408C0509566
:1010F0004095309521953F4F4F4F5F4F0895909504
:101100008095709561957F4F8F4F9F4F0895EE0F9B
:0E111000FF1F0590F491E02D0994F894FFCF95
:10111E0014003200000340000004400000020800EA
:0A112E0000000000000000000000B7
:00000001FF

View File

@@ -1 +1 @@
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem14201 -b 19200 -p m16u2 -vvv -U flash:r:16u2-out3.hex:i avrdude -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:r:16u2-out.hex:i

View File

@@ -13,4 +13,4 @@ REM remove blank
SET COMPORT=%COMX: =% SET COMPORT=%COMX: =%
..\tools\win\tool-avrdude\avrdude -C ..\tools\win\tool-avrdude\avrdude.conf -c arduino -P %COMPORT% -b 19200 -p m16u2 -vvv -U flash:w:16u2.hex:i ..\tools\win\tool-avrdude\avrdude -C ..\tools\win\tool-avrdude\avrdude.conf -c arduino -P %COMPORT% -b 19200 -p m16u2 -vvv -U flash:w:Arduino-usbserial.hex:i

View File

@@ -1 +1 @@
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem14201 -b 19200 -p m16u2 -vvv -U flash:w:16u2.hex:i avrdude -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:w:Arduino-usbserial.hex:i

View File

@@ -1 +1,3 @@
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem14201 -b 19200 -p m16u2 -vvv -U flash:w:16u2-original.hex:i #avrdude should be installed via homebrew
#avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:w:16u2-original.hex:i
avrdude -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:w:16u2-original.hex:i

View File

@@ -0,0 +1,3 @@
#avrdude should be installed via homebrew
#avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:w:16u2-original.hex:i
avrdude -c arduino -P /dev/cu.usbmodem144101 -b 19200 -p m16u2 -vvv -U flash:w:16u2-italiano.hex:i

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,3 +1,3 @@
export PORT=cu.usbmodem14101 export PORT=cu.usbmodem144101
echo . | stty -f /dev/$PORT speed 1200 echo . | stty -f /dev/$PORT speed 1200
../tools/mac/tool-bossac/bossac -U false -p $PORT -i -e -w -v -b firmware.bin -R ../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R

View File

@@ -1 +1 @@
../tools/mac/arduinoOTA -address 192.168.11.172 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch ../tools/mac/arduinoOTA -address 192.168.11.13 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch

View File

@@ -0,0 +1,3 @@
export PORT=cu.usbmodem144101
echo . | stty -f /dev/$PORT speed 1200
../tools/mac/tool-bossac/bossac -p $PORT -i -w -v -b firmware.bin -R

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,273 +0,0 @@
:10000000A7C00000C0C00000BEC00000BCC000000F
:10001000BAC00000B8C00000B6C00000B4C0000004
:10002000B2C00000B0C00000AEC00000C1C40000FB
:1000300085C40000A8C00000A6C00000A4C0000045
:10004000A2C00000A0C000009EC000009CC0000034
:100050009AC0000098C0000096C0000021C10000B6
:1000600092C0000090C000008EC000008CC0000054
:100070008AC0000088C0000086C0000084C0000064
:1000800082C0000080C000007EC000007CC0000074
:100090007AC0000078C000001201100102000008C0
:1000A00041233D0001000102DC0109023E00020182
:1000B00000C0320904000001020201000524000111
:1000C0001004240206052406000107058203080027
:1000D000FF09040100020A000000070504024000B5
:1000E00001070583024000010403090432034100B3
:1000F00072006400750069006E006F002000280027
:100100007700770077002E006100720064007500B0
:1001100069006E006F002E0063006300290000007C
:100120002E03410072006400750069006E006F00CC
:1001300020004400750065002000500072006F0030
:1001400067002E00200050006F0072007400000055
:1001500011241FBECFEFD2E0DEBFCDBF11E0A0E083
:10016000B1E0E4EDF0E102C005900D92A831B107D5
:10017000D9F712E0A8E1B1E001C01D92A833B107A0
:10018000E1F72BD1A5C73CCF9C01DC01AE57BF4F97
:10019000ED91FC91119741911196FC93EE9380584B
:1001A0009F4FE817F90711F42D933C939FB7F894EC
:1001B000F901EC57FF4F8081815080839FBF842FCE
:1001C0000895882311F03F9A01C03F9847980895F9
:1001D000882311F046980895469A0895DF92EF9289
:1001E000FF920F931F93FC018489813019F08230B4
:1001F00019F404C010E303C010E001C010E28389C9
:10020000823009F418608589873031F0883031F008
:10021000863029F4126003C0146001C01660109289
:10022000C9001092C8001092CA000785F088E188C2
:10023000D288202F3F2D4E2D5D2D10921E01203B88
:1002400084E0380780E0480780E0580719F481E02F
:1002500080931E01CA01B90122E030E040E050E085
:100260001CD720583B47414E5F4FCA01B901202F90
:100270003F2D4E2D5D2DEFD6215030403093CD00D7
:100280002093CC001093CA0082E08093C80088E9D4
:100290008093C9001F910F91FF90EF90DF90089518
:1002A0001F920F920FB60F9211242F938F939F934B
:1002B000EF93FF939091CE008EB38430F1F4E091F0
:1002C000A201F091A3019083E091A201F091A3011A
:1002D000CF0101969093A3018093A201825A91408D
:1002E00021F482E291E0928381839FB7F894809118
:1002F000A6018F5F8093A6019FBFFF91EF919F9111
:100300008F912F910F900FBE0F901F901895FC01A9
:1003100040911A0140931B0180911C0180931D01A3
:100320008585282F30E02170307020931A01858553
:1003300090E096958795817080931C0180911E01B5
:10034000882339F088E790E0909319018093180191
:100350000895442341F4222331F082E390E0909306
:10036000190180931801089580E091E00AC680E0A9
:1003700091E0BDC584B7877F84BF88E10FB6F8944C
:1003800080936000109260000FBE81E01ADF16BCFF
:1003900083E085BD86B58831E8F315BC16BC80E0E6
:1003A00010DF469A3E9A87E690E09093CD008093C6
:1003B000CC0086E08093CA001092C80088E1809348
:1003C000C900539A5A9A8AB180638AB98BB1806303
:1003D0008BB9A9D284E085BD08950F931F93CF9365
:1003E000DF93C8DF2FB7F89487EA91E09093280253
:1003F0008093270290932A02809329022FBF2FB760
:10040000F89482E291E09093A3018093A2019093EB
:10041000A5018093A4012FBF7894C7EAD1E003E03F
:100420008FB7F89490912B028FBF903809F180E03C
:1004300091E0D3D497FD1CC0E0912702F0912802EF
:100440008083E0912702F0912802CF0101969093DA
:100450002802809327028752924011F4D283C183ED
:100460009FB7F89480912B028F5F80932B029FBFE0
:100470008FB7F8941091A6018FBFA89903C01136C9
:1004800008F456C0A89A8091A601882361F05D986F
:1004900000931F0108C082E291E076DE682F80E0C1
:1004A00091E001D511501123B1F780911F018823EC
:1004B00051F080911F01815080931F0180911F0195
:1004C000882309F45D9A80912001882351F080915E
:1004D000200181508093200180912001882309F41C
:1004E0005C9A809118019091190118161906E4F48C
:1004F000CC97CD9710F481E001C080E069DE809157
:100500001801909119010197C29710F481E001C080
:1005100080E057DE80911801909119010197909326
:1005200019018093180104C080E052DE80E049DEAA
:100530008FB7F89490912B028FBF992369F087EAC7
:1005400091E022DE982F8091C80085FFFCCF909328
:10055000CE005C980093200180E091E095D42AD4ED
:100560005FCFDA01923049F0933061F09130F9F4C5
:10057000E8E9F0E022E130E01EC0EAEAF0E02EE334
:1005800030E019C0813049F0813018F0823079F4C0
:1005900008C0E8EEF0E0849107C0ECEEF0E0849152
:1005A00003C0E0E2F1E08491282F30E004C0E0E0F5
:1005B000F0E020E030E0ED93FC93C901089528E0DD
:1005C00030E040E003C04F5F220F331F2817390788
:1005D000D0F3842F8295807F08958093E9008091E5
:1005E000EB0081608093EB001092ED006093EC00D3
:1005F0004093ED008091EE00881F8827881F0895A2
:100600001092F40090E09093E9001092F0001092A4
:10061000E8001092ED008091EB008E7F8093EB005C
:100620009F5F953081F708958091300288238CF484
:1006300003C08EB38823B1F08091E80082FFF9CF28
:100640008091E8008B778093E80008958EB388232B
:1006500049F08091E80080FFF9CF8091E8008E7723
:100660008093E800089594E68091EC0080FF05C037
:100670008091E80080FF05C023C08091E80082FDE2
:100680001FC08EB3882311F482E008958EB38530A5
:1006900011F483E008958091EB0085FF02C081E0B2
:1006A00008958091E10082FFDFCF8091E1008B7F90
:1006B0008093E100992311F484E008959150D4CF00
:1006C00080E008959C014091360250913702461710
:1006D000570718F4F90120E038C06115710511F0D1
:1006E000AB01F8CF8091E8008E778093E80040E07E
:1006F00050E0F0CF8091E80083FF02C081E00895D0
:100700008091E80082FD2DC08EB3882381F18EB3E5
:10071000853079F18091E80080FF17C09091F20058
:1007200006C081918093F100415050409F5F411578
:10073000510511F09830A8F320E0983009F421E039
:100740008091E8008E778093E8004115510591F67D
:10075000222381F606C08EB3882349F08EB38530FC
:1007600041F08091E80082FFF6CF80E0089582E0BA
:10077000089583E008959C0140913602509137021C
:100780004617570710F490E03BC06115710511F052
:10079000AB01F9CF8091E8008E778093E80040E0CC
:1007A00050E0F1CF8091E80083FF02C081E008951E
:1007B0008091E80082FD30C08EB3882399F18EB31A
:1007C000853091F18091E80080FF1AC08091F2009D
:1007D00009C0F9012F5F3F4FE491E093F1004150D0
:1007E00050408F5F4115510511F0883090F390E033
:1007F000883009F491E08091E8008E778093E800DA
:100800004115510579F6992369F606C08EB3882300
:1008100049F08EB3853041F08091E80082FFF6CF39
:1008200080E0089582E0089583E008959C016115B9
:10083000710529F48091E8008B778093E800F90135
:1008400020C08091E80083FF02C081E008958EB34C
:10085000882339F18EB3853031F18091E80082FF31
:10086000F0CF06C08091F10081936150704021F07B
:100870008091F2008823B1F78091E8008B77809314
:10088000E80061157105E9F606C08EB3882349F0CA
:100890008EB3853041F08091E80080FFF6CF80E094
:1008A000089582E0089583E0089542D044D01EBAAE
:1008B00010922E0210922D0210922C0284E089BD1B
:1008C00089B5826089BD09B400FEFDCF8091D80052
:1008D000982F9F779093D80080688093D80080915C
:1008E00063008E7F809363008091D8008F7D80931A
:1008F000D8008091E0008E7F8093E0008091E1003D
:100900008E7F8093E1008091E20081608093E2001D
:100910008091E100877F8093E1008091E200886010
:100920008093E2000895C1DF81E080932F02089553
:100930001092E20008951092E10008951F920F9224
:100940000FB60F9211241F932F933F934F935F93F2
:100950006F937F938F939F93AF93BF93EF93FF9387
:10096000E9EEF0E0108117701082E0EFF0E0808196
:10097000877F80837894C3D0F894A9EEB0E01C926E
:10098000E0EFF0E08081886080831C93FF91EF911D
:10099000BF91AF919F918F917F916F915F914F9197
:1009A0003F912F911F910F900FBE0F901F901895A0
:1009B0001F920F920FB60F9211242F933F934F93D4
:1009C0005F936F937F938F939F93AF93BF93EF93B7
:1009D000FF938091E10080FF1BC08091E20080FFC7
:1009E00017C08091E1008E7F8093E1008091E2004A
:1009F0008E7F8093E2008091E20080618093E2002C
:100A00008091D80080628093D80019BC1EBAD1D1E1
:100A10008091E10084FF29C08091E20084FF25C01D
:100A200084E089BD89B5826089BD09B400FEFDCF2F
:100A30008091D8008F7D8093D8008091E1008F7ED7
:100A40008093E1008091E2008F7E8093E2008091AC
:100A5000E20081608093E20080912E02882311F4ED
:100A600081E001C084E08EBBA4D18091E10083FFCE
:100A700027C08091E20083FF23C08091E100877F3F
:100A80008093E10082E08EBB10922E028091E10003
:100A90008E7F8093E1008091E2008E7F8093E20060
:100AA0008091E20080618093E200AADD80E060E056
:100AB00042E093DD8091F00088608093F00079D16E
:100AC0008091E10082FF0AC08091E20082FF06C0AF
:100AD0008091E1008B7F8093E1006BD1FF91EF91DA
:100AE000BF91AF919F918F917F916F915F914F9146
:100AF0003F912F910F900FBE0F901F9018951F934D
:100B0000DF93CF93CDB7DEB7AC970FB6F894DEBFC7
:100B10000FBECDBFE0E3F2E08091F100819322E0CF
:100B2000E833F207C9F78091300230913102353055
:100B300009F487C0363040F43130C9F1313070F0FB
:100B4000333009F01DC133C0383009F4EFC03930FB
:100B500009F4FEC0363009F013C192C0803821F08C
:100B6000823809F00DC108C090912C0280912D02AD
:100B7000882399F0926011C080913402877080932D
:100B8000E9008091EB0090E025E0969587952A9505
:100B9000E1F7982F91701092E9008091E800877F2B
:100BA0008093E8009093F1001092F100CAC088236E
:100BB00019F0823009F0E4C090E08F7190700097D6
:100BC00021F0029709F0DDC00CC080913202813023
:100BD00009F0D7C010922D02333069F580932D02B1
:100BE0002AC080913202882331F520913402277087
:100BF00009F4C7C02093E9008091EB0080FFC1C0D9
:100C0000333021F48091EB00806213C08091EB00BF
:100C100080618093EB0081E090E002C0880F991F13
:100C20002A95E2F78093EA001092EA008091EB00A7
:100C300088608093EB001092E9008091E800877F44
:100C400083C0882309F09CC0109132028091E80093
:100C5000877F8093E800E8DC04C08EB3882309F422
:100C600090C08091E80080FFF8CF812F8F7711F43A
:100C700092E001C093E09EBB80688093E30081C056
:100C80008058823008F07CC080913202909133020B
:100C900023E08C3D920799F55FB7F894DE01159635
:100CA0004EE020E030E061E2E42FF0E06093570096
:100CB000849120FF03C082958F704F5F982F9F70A3
:100CC000892F805D8A3308F0895F8C9311961C927E
:100CD00011972F5F3F4F12962431310529F75FBFDF
:100CE0008AE28B8383E08C838091E800877F809306
:100CF000E800CE0103966AE270E0E4DC11C0609186
:100D00003402AE014F5F5F4F2CDCBC010097C9F18C
:100D10008091E800877F8093E80089819A812BDDAC
:100D20008091E8008B778093E8002BC0803841F5F4
:100D30008091E800877F8093E80080912E02809365
:100D4000F1008091E8008E778093E8006DDC19C097
:100D50008823B1F490913202923098F48091E800A7
:100D6000877F8093E80090932E025EDC80912E02B4
:100D7000882311F483E001C084E08EBBF8DA01C05F
:100D8000F3DA8091E80083FF0AC08091EB00806273
:100D90008093EB008091E800877F8093E800AC9619
:100DA0000FB6F894DEBF0FBECDBFCF91DF911F917C
:100DB000089508951F938EB3882361F01091E90080
:100DC0001092E9008091E80083FF01C098DE17705F
:100DD0001093E9001F9108950895FC018EB38430AB
:100DE00021F587859089A189B2890097A105B10570
:100DF000E1F085818093E9008091E80082FF15C0D1
:100E00008091F200882319F42FEF3FEF04C0809106
:100E1000F100282F30E08091F200882341F4809186
:100E2000E8008B778093E80002C02FEF3FEFC90105
:100E30000895FC018EB3843011F587859089A189CE
:100E4000B2890097A105B105D1F081818093E900B5
:100E50008091F2008823A9F09091E8008091E80049
:100E60008E778093E80095FD0CC0FDDB982F8823DA
:100E700049F48091E8008E778093E80003C092E007
:100E800001C090E0892F0895FC018EB3843051F4A5
:100E900087859089A189B2890097A105B10511F0D4
:100EA000CF01C7CF08951F93FC01162F8EB3843056
:100EB000D9F487859089A189B2890097A105B105E8
:100EC00099F081818093E9008091E80085FD08C058
:100ED0008091E8008E778093E800C5DB882329F4B1
:100EE0001093F10080E001C082E01F9108950F93FC
:100EF0001F93CF93DF93EC010D96FC0189E0DF0196
:100F00001D928A95E9F72A813B8109818C8188238A
:100F100011F410E001C014E0C90151DB182B12607C
:100F2000802F61E8412F59DB882329F12E813F81F1
:100F30000D818885882311F410E001C014E0C901F7
:100F40003EDB182B1260802F60E8412F46DB8823A0
:100F500091F02A853B8509858C85882311F410E062
:100F600001C014E0C9012BDB182B1260802F61EC4B
:100F7000412F33DB01C080E0DF91CF911F910F91B2
:100F80000895CF93DF93EC018091E80083FF60C068
:100F9000888190E02091340230913502281739077A
:100FA00009F056C080913102813261F0823220F422
:100FB000803209F04DC019C0823269F1833209F0E4
:100FC00047C038C080913002813A09F041C0809119
:100FD000E800877F8093E800CE010F9667E070E01D
:100FE00071DB8091E8008B7713C0809130028132F1
:100FF00079F58091E800877F8093E800CE010F9615
:1010000067E070E013DCCE01E9D88091E8008E77CC
:101010008093E8001DC0809130028132C9F4809134
:10102000E800877F8093E800809132028D87CE01AF
:101030006ED90DC080913002813251F48091E80068
:10104000877F8093E800CE0160913202C5DEECDA42
:10105000DF91CF910895A1E21A2EAA1BBB1BFD01BF
:101060000DC0AA1FBB1FEE1FFF1FA217B307E40787
:10107000F50720F0A21BB30BE40BF50B661F771FDF
:10108000881F991F1A9469F76095709580959095BF
:101090009B01AC01BD01CF01089597FB092E0526E8
:1010A0000ED057FD04D0D7DF0AD0001C38F450957D
:1010B0004095309521953F4F4F4F5F4F0895F6F77C
:1010C00090958095709561957F4F8F4F9F4F0895B4
:0410D000F894FFCFC2
:1010D400000340000004400000020800000000007B
:0810E4000000000000001400F0
:00000001FF

View File

@@ -1,2 +0,0 @@
This package need if you have problem with unrelable cold start of Arduino DUE
Arduino ISP should be connected to 16u2 ICSP connector before run

View File

@@ -1 +0,0 @@
../../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -c arduino -P /dev/cu.usbmodem1411 -b 19200 -p m16u2 -vvv -U flash:w:16u2.hex:i

View File

@@ -1 +0,0 @@
libavrdude.1.dylib

View File

@@ -1,41 +0,0 @@
# libavrdude.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.6
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname='libavrdude.1.dylib'
# Names of this library.
library_names='libavrdude.1.dylib libavrdude.dylib'
# The name of the static archive.
old_library='libavrdude.a'
# Linker flags that cannot go in dependency_libs.
inherited_linker_flags=' '
# Libraries that this one depends upon.
dependency_libs=' -L/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib -lreadline -lncurses -ltermcap'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libavrdude.
current=1
age=0
revision=0
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib'

View File

@@ -1,41 +0,0 @@
# libusb-1.0.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.2
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname=''
# Names of this library.
library_names=''
# The name of the static archive.
old_library='libusb-1.0.a'
# Linker flags that can not go in dependency_libs.
inherited_linker_flags=' '
# Libraries that this one depends upon.
dependency_libs=' -lobjc'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libusb-1.0.
current=1
age=1
revision=0
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib'

View File

@@ -1,81 +0,0 @@
#!/bin/sh
prefix=/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
exec_prefix_set=no
usage()
{
cat <<EOF
Usage: libusb-config [OPTIONS] [LIBRARIES]
Options:
[--prefix[=DIR]]
[--exec-prefix[=DIR]]
[--version]
[--libs]
[--cflags]
EOF
exit $1
}
if test $# -eq 0; then
usage 1 1>&2
fi
while test $# -gt 0; do
case "$1" in
-*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) optarg= ;;
esac
case $1 in
--prefix=*)
prefix=$optarg
if test $exec_prefix_set = no ; then
exec_prefix=$optarg
fi
;;
--prefix)
echo_prefix=yes
;;
--exec-prefix=*)
exec_prefix=$optarg
exec_prefix_set=yes
;;
--exec-prefix)
echo_exec_prefix=yes
;;
--version)
echo 0.1.12
exit 0
;;
--cflags)
if test "$includedir" != /usr/include ; then
includes="-I$includedir"
fi
echo_cflags=yes
;;
--libs)
echo_libs=yes
;;
*)
usage 1 1>&2
;;
esac
shift
done
if test "$echo_prefix" = "yes"; then
echo $prefix
fi
if test "$echo_exec_prefix" = "yes"; then
echo $exec_prefix
fi
if test "$echo_cflags" = "yes"; then
echo $includes
fi
if test "$echo_libs" = "yes"; then
echo -L$libdir -lusb
fi

View File

@@ -1,41 +0,0 @@
# libusb.la - a libtool library file
# Generated by libtool (GNU libtool) 2.4.2
#
# Please DO NOT delete this file!
# It is necessary for linking the library.
# The name that we can dlopen(3).
dlname=''
# Names of this library.
library_names=''
# The name of the static archive.
old_library='libusb.a'
# Linker flags that can not go in dependency_libs.
inherited_linker_flags=' '
# Libraries that this one depends upon.
dependency_libs=' -L/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib /Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib/libusb-1.0.la -lobjc'
# Names of additional weak libraries provided by this library
weak_library_names=''
# Version information for libusb.
current=8
age=4
revision=4
# Is this an already installed library?
installed=yes
# Should we warn about portability when linking against -modules?
shouldnotlink=no
# Files to dlopen/dlpreopen
dlopen=''
dlpreopen=''
# Directory that this library needs to be installed in:
libdir='/Users/jenkins/jenkins/workspace/avrdude/label/mac-mini/objdir/lib'

View File

@@ -1,13 +1,18 @@
#include "abstractch.h" #include "abstractch.h"
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
#endif
#include "utils.h" #include "utils.h"
#include <aJSON.h> #include <aJSON.h>
#include "main.h" #include "main.h"
extern lan_status lanStatus; extern lan_status lanStatus;
#if not defined (NOIP)
extern PubSubClient mqttClient; extern PubSubClient mqttClient;
extern int8_t ethernetIdleCount; extern int8_t ethernetIdleCount;
#endif
int abstractCh::publishTopic(const char* topic, long value, const char* subtopic) int abstractCh::publishTopic(const char* topic, long value, const char* subtopic)
{ {
@@ -25,6 +30,7 @@ int abstractCh::publishTopic(const char* topic, float value, const char* subtopi
int abstractCh::publishTopic(const char* topic, const char * value, const char* subtopic) int abstractCh::publishTopic(const char* topic, const char * value, const char* subtopic)
{ {
#if not defined (NOIP)
char addrstr[MQTT_TOPIC_LENGTH]; char addrstr[MQTT_TOPIC_LENGTH];
if (!isNotRetainingStatus()) return 0; if (!isNotRetainingStatus()) return 0;
if (topic) if (topic)
@@ -38,5 +44,6 @@ int abstractCh::publishTopic(const char* topic, const char * value, const char*
return 1; return 1;
} }
} }
#endif
return 0; return 0;
}; };

View File

@@ -4,6 +4,7 @@
#define CST_UNKNOWN 0 #define CST_UNKNOWN 0
#define CST_FAILED 1 #define CST_FAILED 1
#define CST_INITIALIZED 2 #define CST_INITIALIZED 2
#define CST_USER 3
class abstractCh { class abstractCh {
public: public:
@@ -11,7 +12,7 @@ public:
virtual ~abstractCh(){}; virtual ~abstractCh(){};
virtual int Poll(short cause) {return 0;} virtual int Poll(short cause) {return 0;}
virtual int Setup() =0; //Should initialize hardware and reserve resources virtual int Setup() =0; //Should initialize hardware and reserve resources
virtual int Anounce () {return 0;}; // virtual int Anounce () {return 0;};
virtual int Stop() {return 0;}; //Should free resources virtual int Stop() {return 0;}; //Should free resources
virtual int Status() {return CST_UNKNOWN;} virtual int Status() {return CST_UNKNOWN;}
virtual void setStatus(uint8_t status) {} virtual void setStatus(uint8_t status) {}

View File

@@ -1,14 +1,17 @@
#include "abstractin.h" #include "abstractin.h"
#include "abstractch.h" #include "abstractch.h"
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
extern PubSubClient mqttClient;
#endif
#include "utils.h" #include "utils.h"
#include <aJSON.h> #include <aJSON.h>
#include "inputs.h" #include "inputs.h"
#include "main.h" #include "main.h"
extern lan_status lanStatus; extern lan_status lanStatus;
extern PubSubClient mqttClient;
int abstractIn::publish(long value, const char* subtopic) int abstractIn::publish(long value, const char* subtopic)
{ {

View File

@@ -13,7 +13,7 @@ public:
virtual bool isAllowed(itemCmd cmd){return true;}; virtual bool isAllowed(itemCmd cmd){return true;};
virtual itemCmd getDefaultOnVal(){return itemCmd().Percents255(255);}; virtual itemCmd getDefaultOnVal(){return itemCmd().Percents255(255);};
virtual int getChanType(){return 0;} virtual int getChanType(){return 0;}
virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead // virtual int getDefaultStorageType(){return 0;} /// Remove?? Now getChanType used instead
virtual int Status() override; virtual int Status() override;
virtual void setStatus(uint8_t status) override; virtual void setStatus(uint8_t status) override;
int Setup() override; int Setup() override;

918
lighthub/candriver.cpp Normal file
View File

@@ -0,0 +1,918 @@
#ifdef CANDRV
#include <candriver.h>
#include <Arduino.h>
#include <main.h>
#include <utils.h>
#if defined(ARDUINO_ARCH_STM32)
#include <STM32_CAN.h>
STM32_CAN STMCan( CAN1, CAN_PINS::DEF, RX_SIZE_64, TX_SIZE_16 );
#endif
#if defined(ARDUINO_ARCH_ESP32)
#include <CAN.h>
#endif
#if defined(__SAM3X8E__)
#include <due_can.h>
#endif
#include <config.h>
//#include <systemconfigdata.h>
extern systemConfig sysConf;
extern canStream CANConfStream;
extern aJsonObject * root;
extern volatile int8_t configLocked;
extern bool configLoaded;
void printFrame(datagram_t * frame, uint8_t len ) {
debugSerial.print(" Data:");
for (int count = 0; count < len; count++) {
debugSerial.print(frame->data[count], HEX);
debugSerial.print(" ");
}
debugSerial.println();
}
bool canDriver::upTime(uint32_t ut)
{
if (!controllerId) return false;
canid_t id;
datagram_t packet;
id.reserve=0;
id.status=1;
id.payloadType=payloadType::metric;
id.deviceId=controllerId;
id.subjId=metricType::UpTime;
packet.metric1=ut;
debugSerial<<("CAN: UpTime")<<endl;
return write (id.id, &packet, 4);
}
bool canDriver::salt(uint32_t salt)
{
if (!controllerId) return false;
canid_t id;
datagram_t packet;
id.reserve=0;
id.status=1;
id.payloadType=payloadType::metric;
id.deviceId=controllerId;
id.subjId=metricType::Salt;
packet.metric1=salt;
debugSerial<<("CAN: Salt")<<endl;
return write (id.id, &packet, 4);
}
bool canDriver::lookupMAC()
{
// return 0;
canid_t id;
datagram_t packet;
bool res;
id.reserve=0;
id.status=0;
id.payloadType=payloadType::lookupMAC;
id.deviceId=0;
id.subjId=0; //CRC?
memcpy(packet.mac,sysConf.mac,6);
debugSerial<<("CAN: Lookup MAC")<<endl;
res=write (id.id, &packet, 6);
if (res) state=canState::MACLookup;
else state=canState::Error;
responseTimer=millisNZ();
return res;
}
bool canDriver::requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo )
{
canid_t id;
datagram_t packet;
bool res;
id.reserve=0;
id.status=0;
id.payloadType=_payloadType;
id.deviceId=devId;
id.subjId=seqNo;
packet.metric1 =0;
//memcpy(packet.mac,sysConf.mac,6);
//delay (100);
debugSerial<<("CAN: Request frame ")<<_payloadType<<F(" for id ")<<devId<<F(" seq:")<<seqNo<<endl;
res=write (id.id,&packet,1);
if (res) state=canState::FrameRequested;
else state=canState::Error;
responseTimer=millisNZ();
return res;
}
bool canDriver::sendRemoteID(macAddress mac)
{
canid_t id;
//datagram_t packet;
bool res=false;
id.deviceId=getIdByMac(mac); //Retrieved controllerID
if (!id.deviceId) return false;
id.reserve=0;
id.status=1; //response
id.payloadType=payloadType::lookupMAC;
id.subjId=200; //CRC16 of remote config
debugSerial<<("CAN: Send remote ID")<<endl;
res = write (id.id,(datagram_t*)mac,6);
if (res) state=canState::Idle;
else state=canState::Error;
// responseTimer=millisNZ(); ????????
return res;
}
bool canDriver::begin()
{
controllerId = getMyId();
if (!ready) // not reInitialization
{
ready=false;
//STM32
#if defined(ARDUINO_ARCH_STM32)
//Can= new STM32_CAN( CAN1, ALT );
//if (!Can) return false;
STMCan.begin(); //with retransmission
STMCan.setBaudRate(50000);
// STMCan.setFilter( 0, 0x153, 0x1FFFFFFF );
#endif
//ESP
#if defined(ARDUINO_ARCH_ESP32)
CAN.setPins(GPIO_NUM_35,GPIO_NUM_5);//(rx, tx);
// start the CAN bus at 500 kbps
if (!CAN.begin(50000)) {return false; }
#endif
#if defined(__SAM3X8E__)
Can0.begin(CAN_BPS_50K);
int filter;
//extended
for (filter = 0; filter < 3; filter++) {
Can0.setRXFilter(filter, 0, 0, true);
//Can1.setRXFilter(filter, 0, 0, true);
}
#endif
ready=true;
}
debugSerial<<"CAN: initialized. addr="<<controllerId<<endl;
return true;
}
int canDriver::readFrame()
{
if (!ready) return -1;
//STM32
#if defined(ARDUINO_ARCH_STM32)
if (STMCan.read(CAN_RX_msg))
{
if (CAN_RX_msg.len>8) CAN_RX_msg.len=8;
memcpy(RXpacket.data, CAN_RX_msg.buf,CAN_RX_msg.len);
RXlen = CAN_RX_msg.len;
RXid.id = CAN_RX_msg.id;
return RXlen;
}
#endif
#if defined(ARDUINO_ARCH_ESP32)
// try to parse packet
int packetSize = CAN.parsePacket();
if (packetSize ){//|| CAN.packetId() != -1) {
// received a packet
debugSerialPort.print("CAN: Received ");
if (CAN.packetExtended()) {
debugSerialPort.print("extended ");
}
if (CAN.packetRtr()) {
// Remote transmission request, packet contains no data
debugSerialPort.print("RTR ");
}
debugSerialPort.print("packet with id 0x");
debugSerialPort.print(CAN.packetId(), HEX);
if (CAN.packetRtr()) {
debugSerialPort.print(" and requested length ");
debugSerialPort.println(CAN.packetDlc());
} else {
debugSerialPort.print(" and length ");
//debugSerialPort.println(packetSize);
debugSerialPort.println(CAN.packetDlc());
// only print packet data for non-RTR packets
RXlen=0;
while (CAN.available()) {
RXpacket.data[RXlen++]=CAN.read();
if (RXlen>=8) break;
}
RXid.id = CAN.packetId();
debugSerialPort.println();
return RXlen;
}
}
#endif
//DUE
#if defined(__SAM3X8E__)
CAN_FRAME CAN_RX_msg;
if (Can0.available() > 0) {
Can0.read(CAN_RX_msg);
if (CAN_RX_msg.length>8) CAN_RX_msg.length=8;
memcpy(RXpacket.data, CAN_RX_msg.data.bytes,CAN_RX_msg.length);
RXlen = CAN_RX_msg.length;
RXid.id = CAN_RX_msg.id;
return RXlen;
}
#endif
return -1;
}
void canDriver::Poll()
{
if (readFrame()>=0) processPacket( RXid, &RXpacket, RXlen);
//State machine
switch (state)
{
case canState::MACLookup:
// case canState::FrameRequested:
if (isTimeOver(responseTimer,millis(),1000UL))
{
responseTimer=millisNZ();
state=canState::Error;
errorSerial<<"CAN: lookup Timeout"<<endl;
}
break;
case canState::Error:
if (configLoaded) state=canState::ConfigLoaded;
else
if (isTimeOver(responseTimer,millis(),10000UL))
lookupMAC();
break;
case canState::ReadConfig:
{
//Blocking read config
if (configLocked) return; // only in safe moments
configLocked++;
infoSerial<<F("CAN: Requesting Config")<<endl;
CANConfStream.open(controllerId,payloadType::configFrame,'r');
if (CANConfStream.peek() == '{') {
debugSerial<<F("CAN: JSON detected")<<endl;
aJsonStream as = aJsonStream(&CANConfStream);
cleanConf(false);
root = aJson.parse(&as);
CANConfStream.close();
if (!root) {
errorSerial<<F("CAN: config load failed")<<endl;
sysConf.setETAG("");
// sysConfStream.close();
configLocked--;
state = canState::Error;
return;
}
infoSerial<<F("CAN: config Loaded")<<endl;
configLocked--;
applyConfig();
sysConf.loadETAG();
state = canState::Idle;
return ;
}
CANConfStream.close();
infoSerial<<F("CAN: Config not loaded")<<endl;
state = canState::Error;
configLocked--;
}
break;
// case canState::Idle:
}
}
bool canDriver::processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr)
{
debugSerial.print("CAN: Rcvd ");
debugSerial.print(len);
debugSerial.print(" bytes id:");
debugSerial.println(id.id,HEX);
//if (id.deviceId && (id.deviceId != controllerId) && !id.status) return false;
debugSerial<<"CAN: " ;
if (id.status) debugSerial.print("Resp "); else debugSerial.print("Req ");
debugSerial<<"(devId:"<< id.deviceId <<" ";
switch ((id.payloadType)){
case payloadType::itemCommand:
debugSerial.print("itemCmd");
debugSerial<<" itemId:"<< id.itemId;
if (id.subItemId!=NO_SUBITEM) debugSerial << " subItem:"<<id.subItemId;
if (id.deviceId && (id.deviceId != controllerId) && !id.status) //ignore requests with NON ZERO devId where another CANID
{
debugSerial.println(")");
return false;
}
break;
case payloadType::lookupMAC:
debugSerial.print("lookupMAC");
if (id.status && (memcmp(packet->mac, sysConf.mac,6))) //Ignore responses for another controller
{
debugSerial.println(")");
return false;
}
break;
case payloadType::configFrame:
debugSerial.print("configFrame #");
debugSerial<< id.subjId;
if (id.status && (id.deviceId != controllerId)) //Ignore responses on config request not for me
{
debugSerial.println(")");
return false;
}
break;
case payloadType::OTAFrame:
debugSerial.print("OTAFrame #");
debugSerial<< id.subjId;
break;
case payloadType::auth:
debugSerial.print("auth #");
debugSerial<< id.subjId;
break;
case payloadType::metric:
debugSerial.print("metric #");
debugSerial<< id.subjId;
break;
case payloadType::sysCmd:
debugSerial.print("sysCmd");
if (id.deviceId != controllerId) //Ignore commands not for me
{
debugSerial.println(")");
return false;
}
break;
case payloadType::rawPinCtrl:
debugSerial.print("rawPinCtrl");
if (id.deviceId != controllerId) //Ignore commands not for me
{
debugSerial.println(")");
return false;
}
}
debugSerial<< ") ";
if (len) printFrame(packet,len);
if (id.status){
//Responces
//@ any state
switch (id.payloadType)
{
case payloadType::itemCommand:
{
if (len!=8) return false;
aJsonObject *confObj = findConfbyID(id.deviceId);
if (confObj)
{
debugSerial<<F("CAN: status received for dev ")<<id.deviceId<<endl;
//char * itemNName = findItemName(id.itemId);
aJsonObject *itemsObj = aJson.getObjectItem(confObj,"items");
if (!itemsObj) return false;
Item it(id.itemId, id.subjId, itemsObj);
if (it.isValid())
{
itemCmd ic;
uint16_t flags = 0;
ic.cmd = packet->cmd;
ic.param = packet->param;
debugSerial<<F("CAN: item ")<<it.itemArr->name;
ic.debugOut();
if (ic.isCommand()) flags |= FLAG_COMMAND;
if (ic.isValue()) flags |= FLAG_PARAMETERS;
ic.saveItem(&it,flags);
it.SendStatusImmediate(ic,flags | FLAG_NOT_SEND_CAN,it.getSubItemStrById(id.subItemId));
return true;
}
}
}
break;
}
switch (state)
{
case canState::MACLookup:
if ((id.payloadType == payloadType::lookupMAC))
{
debugSerial<<"\nCAN: Got Controller addr: "<<id.deviceId<<endl;
controllerId=id.deviceId;
state = canState::ReadConfig;
}
return true;
case canState::FrameRequested:
if ((id.payloadType == payloadType::configFrame) && (id.deviceId == controllerId))
{
errorSerial<<F("CAN: Config received when not expected")<<endl;
}
break;
case canState::Idle:
break;
case canState::Error:
return false;
}
}
else //Requests
{
/*
switch (id.payloadType)
{
case payloadType::itemCommand:
break;
case payloadType::sysCmd:
break;
}*/
if ((id.payloadType == payloadType::itemCommand) && (len ==8))
{
Item it(id.itemId,id.subItemId);
if (it.isValid())
{
itemCmd ic;
ic.cmd = packet->cmd;
ic.param = packet->param;
//debugSerial<<F("CAN: itemCmd: ");
//ic.debugOut();
return it.Ctrl(ic,it.getSubItemStrById(id.subItemId));
}
return false;
}
else if ((id.payloadType == payloadType::lookupMAC) && (len>=6))
{
return sendRemoteID(packet->mac);
//debugSerial<<"ID requested"<<endl;
}
else if ((id.payloadType == payloadType::configFrame) && (id.subjId == 0xFFFF))
{
debugSerial<<F("CAN: Requested conf for dev#")<<id.deviceId<<endl;
aJsonObject * remoteConfObj = findConfbyID(id.deviceId);
if (remoteConfObj)
{
infoSerial<<F("CAN: Sending conf for dev#")<<id.deviceId<<endl;
CANConfStream.open(id.deviceId,payloadType::configFrame,'w');
aJsonStream outStream = aJsonStream(&CANConfStream);
aJson.print(remoteConfObj, &outStream);
CANConfStream.close();
}
return 1;
//debugSerial<<"ID requested"<<endl;
}
}
return false;
}
uint8_t canDriver::getMyId()
{
if (!root) return 0;
aJsonObject * canObj = aJson.getObjectItem(root, "can");
if (!canObj) return 0;
aJsonObject * addrObj = aJson.getObjectItem(canObj, "addr");
if (addrObj && (addrObj->type == aJson_Int)) return addrObj->valueint;
return 0;
}
aJsonObject * canDriver::findConfbyID(uint8_t devId)
{
if (!root) return NULL;
aJsonObject * canObj = aJson.getObjectItem(root, "can");
if (!canObj) return NULL;
aJsonObject * remoteConfObj = aJson.getObjectItem(canObj, "conf");
if (!remoteConfObj) return NULL;
remoteConfObj=remoteConfObj->child;
while (remoteConfObj)
{
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
if (remoteCanObj)
{
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
if (addrObj && (addrObj->type == aJson_Int) && (addrObj->valueint == devId)) return remoteConfObj;
}
remoteConfObj=remoteConfObj->next;
}
return NULL;
}
uint8_t canDriver::getIdByMac(macAddress mac)
{
char macStr[19];
uint8_t strptr = 0;
if (!root) return 0;
aJsonObject * canObj = aJson.getObjectItem(root, "can");
if (!canObj) return 0;
aJsonObject * confObj = aJson.getObjectItem(canObj, "conf");
if (!confObj) return 0;
memset(macStr,0,sizeof(macStr));
for (byte i = 0; i < 6; i++)
{
// if (mac[i]<16) macStr[strptr++]='0';
SetBytes(&mac[i],1,&macStr[strptr]);
strptr+=2;
if (i < 5) macStr[strptr++]=':';
}
debugSerial<<F("CAN: Searching devId for ")<<macStr<<endl;
aJsonObject * remoteConfObj = aJson.getObjectItem(confObj, macStr);
if (!remoteConfObj) return 0;
aJsonObject * remoteCanObj = aJson.getObjectItem(remoteConfObj, "can");
if (!remoteCanObj) return 0;
aJsonObject * addrObj = aJson.getObjectItem(remoteCanObj, "addr");
if (!addrObj) return 0;
if (addrObj && (addrObj->type == aJson_Int))
{
debugSerial<<F("CAN: find dev#")<< addrObj->valueint << endl;
return addrObj->valueint;
}
return 0;
}
bool canDriver::write(uint32_t msg_id, datagram_t * buf, uint8_t size)
{ //return 0;
if (!ready) errorSerial<<"CAN: not initialized"<<endl;
bool res;
if (size>8) size = 8;
//STM32
#if defined(ARDUINO_ARCH_STM32)
//if (!Can) return 0;
if (buf) for(uint8_t i=0;i<size; i++) CAN_TX_msg.buf[i]=buf->data[i];
CAN_TX_msg.id = msg_id;
CAN_TX_msg.flags.extended = 1; // To enable extended ID
CAN_TX_msg.len=size;
if (res=STMCan.write(CAN_TX_msg)) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
else debugSerial.println("CAN: Write error");
return res;
#endif
//ESP
#if defined(ARDUINO_ARCH_ESP32)
CAN.beginExtendedPacket(msg_id,size);
CAN.write(buf->data,size);
//for(uint8_t i=0;i<size; i++) CAN.write(buf[i]);
if (res=CAN.endPacket()) debugSerial<< ("CAN: Wrote ")<<size << " bytes, id "<<_HEX(msg_id)<<endl;
else debugSerial.println("CAN: Write error");
return res;
#endif
#if defined(__SAM3X8E__)
CAN_FRAME CAN_TX_msg;
CAN_TX_msg.id = msg_id;
CAN_TX_msg.extended = true;
CAN_TX_msg.length=size;
//outgoing.priority = 4; //0-15 lower is higher priority
if (buf) for(uint8_t i=0;i<size; i++) CAN_TX_msg.data.bytes[i]=buf->data[i];
res=Can0.sendFrame(CAN_TX_msg);
if (res) debugSerial<<("CAN: Wrote ")<<size<<" bytes, id "<<_HEX(msg_id)<<endl;
else debugSerial.println("CAN: Write error");
return res;
#endif
}
bool canDriver::sendStatus(uint16_t itemNum, itemCmd cmd, int subItem)
{
if (!itemNum) return false;
return sendCommand(controllerId, itemNum, cmd, true, subItem);
}
bool canDriver::sendCommand(aJsonObject * can, itemCmd cmd, bool status)
{
if (can && (can->type == aJson_Array))
{
int subItem=NO_SUBITEM;
aJsonObject * dev = aJson.getArrayItem(can,0);
aJsonObject * it = aJson.getArrayItem(can,1);
aJsonObject * sfx = aJson.getArrayItem(can,2);
aJsonObject * subItemObj = aJson.getArrayItem(can,3);
if (sfx)
switch (sfx->type)
{
case aJson_Int: cmd.setSuffix(sfx->valueint);
break;
case aJson_String:
int suffix=txt2subItem(sfx->valuestring);
if (suffix) cmd.setSuffix(suffix);
}
if (subItemObj && subItemObj->type==aJson_Int && subItemObj->valueint>=0 && subItemObj->valueint<63) subItem=subItemObj->valueint;
if (dev && it && dev->type == aJson_Int && it->type == aJson_Int)
return sendCommand(dev->valueint, it->valueint, cmd, status,subItem);
}
return false;
}
bool canDriver::sendCommand(uint8_t devID, uint16_t itemID,itemCmd cmd, bool status,int subItemID )
{
canid_t id;
datagram_t packet;
bool res;
id.reserve=0;
id.status=status?1:0;
id.payloadType=payloadType::itemCommand;
id.deviceId=devID;
id.itemId=itemID;
id.subItemId=subItemID;
packet.cmd = cmd.cmd;
packet.param = cmd.param;
debugSerial << ((status)?"CAN: send Status":"CAN: send Command");
debugSerial<<F(" ->[")<<devID<<":"<<itemID<<"] ";
if (subItemID!=NO_SUBITEM) debugSerial<<F("Subitem:")<<subItemID<<" ";
cmd.debugOut();
res=write (id.id,&packet,8);
//if (res) debugSerial<<F("CAN: sent ok")<<endl;
// else debugSerial<<F("CAN: fail")<<endl;
return res;
}
////////////////////////////// Steream //////////////////////////
int canStream::send(uint8_t len, uint16_t _seqNo)
{
canid_t id;
datagram_t packet;
bool res;
if (!driver) return 0;
id.reserve=0;
id.status=1;
id.payloadType=pType;
id.deviceId=devId;
id.subjId=_seqNo;
res=driver->write (id.id, &writeBuffer, len);
writePos=0;
if (res)
{
//Await check?
return 1;
}
else return 0;
}
int canStream::checkState()
{
bool res = false;
if (!driver) return -1;
switch (state)
{
case canState::StreamOpenedRead:
readPos = 0;
res= driver->requestFrame(devId,pType,seqNo); //Requesting frame;
if (res)
state = canState::FrameRequested;
else
{
state = canState::Error;
return -1;
}
if (seqNo ==0xFFFF) seqNo =0;
//continue
case canState::FrameRequested:
{
int c;
uint32_t timer = millis();
do {
//debugSerial.print(".");
yield();
if ((c=driver->readFrame()>0) && (driver->RXid.deviceId == devId) && (driver ->RXid.payloadType == pType) && driver->RXid.status)
{
state = canState::FrameReceived;
debugSerial<<F("CAN: Payload received ")<< c << "|" <<driver->RXlen<< " "<<driver->RXpacket.payload<<"#"<<driver->RXid.subjId<<endl;
seqNo=driver->RXid.subjId;
failedCount=0;
return driver->RXlen;
}
} while((!isTimeOver(timer,millis(),1000UL)) );
debugSerial<<F("CAN: RX data awaiting timeout #")<<failedCount<<endl;
if (failedCount>=3)
{
state = canState::Error;
return -1;
}
failedCount++;
state = canState::StreamOpenedRead;
}
return -1;
break;
case canState::FrameReceived:
return driver->RXlen;
break;
case canState::waitingConfirm:
if (driver->readFrame()>=0)
{
if (
(driver->RXid.deviceId == devId) &&
(driver->RXid.payloadType == pType) &&
(driver->RXid.status == 0)
)
{
debugSerial<<F("CAN: frame confirmed #")<<driver->RXid.subjId<<endl;
if (seqNo == driver->RXid.subjId)
{
state = canState::StreamOpenedWrite;
seqNo++;
}
else
{
state = canState::Error;
errorSerial<<F("CAN: wrong seqNum")<<endl;
return -1;
}
}
return 0;
}
return driver->RXlen;
break;
case canState::Idle:
return -1;
break;
}
return -1;
};
// Stream methods
int canStream::available()
{
if (!driver) return -1;
int avail = checkState();
return avail;
};
int canStream::read()
{
if (!driver) return -1;
int avail = checkState();
int ch;
if (avail>=0)
{
ch = driver->RXpacket.data[readPos++];
if (readPos>=8) state = canState::StreamOpenedRead;
return ch;
}
else return -1;
};
int canStream::peek()
{
if (!driver) return -1;
int avail = checkState();
int ch;
if (avail>=0)
{
ch = driver->RXpacket.data[readPos];
return ch;
}
else return -1;
};
size_t canStream::write(uint8_t c)
{
//if ((state != canState::StreamOpenedWrite) || (state != canState::waitingConfirm)) return -1;
uint32_t timer = millis();
do
{
checkState();
yield();
//debugSerial.print("*");
if (isTimeOver(timer,millis(),1000UL))
{
state = canState::Error;
errorSerial<<F("CAN: write timeout")<<endl;
return -1;
}
}
while (!availableForWrite() );
writeBuffer.data[writePos++]=c;
if (writePos>=8)
{
bool res = send(8,seqNo);
if (res) state = canState::waitingConfirm;
else state = canState::Error;
return res;
}
return 1; };
void canStream::flush()
{
send(writePos,seqNo);
};
int canStream::availableForWrite()
{
switch (state)
{
case canState::waitingConfirm: return 0;
}
return 1;
}
#endif

230
lighthub/candriver.h Normal file
View File

@@ -0,0 +1,230 @@
#pragma once
#define NO_SUBITEM 63
#ifdef CANDRV
#if defined(ARDUINO_ARCH_STM32)
#if !defined(HAL_CAN_MODULE_ENABLED)
#define HAL_CAN_MODULE_ENABLED
#endif
#include <STM32_CAN.h>
#endif
#include <itemCmd.h>
#include <Stream.h>
#include <aJSON.h>
#include <streamlog.h>
//#include <config.h> NO!
typedef uint8_t macAddress[6];
#pragma pack(push, 1)
typedef union
{
uint32_t id;
struct
{ union
{
struct
{
uint16_t subItemId:6;
uint16_t itemId:10;
};
uint16_t subjId;
};
uint8_t deviceId;
uint8_t payloadType:4;
uint8_t status:1;
uint8_t reserve:3; //0
};
} canid_t;
enum payloadType
{ unknown=0,
itemCommand=1,
lookupMAC=2,
configFrame=3,
OTAFrame=4,
auth=5,
metric=6,
sysCmd=7,
rawPinCtrl=8
};
enum metricType
{
MAC=1,
IP=2,
NetMask=3,
GW=4,
DNS=5,
UpTime=6,
Salt=7
};
enum commandType
{
reboot=1,
get=2,
save=3,
load=4
};
#define MAXCANID 0x1FFFFFFF
// Request item status: id.status=1;deviceId=[0xFF | deviceId];itemId=x; RTR bit=true
// Request on config: id.status=0;deviceId=0;itemId=x payload.mac=mac;crc16=crc_current_config
typedef union {
uint8_t data[8];
char payload[8];
struct {
itemCmdStore cmd;
itemArgStore param;
};
struct {
macAddress mac;
uint16_t currentConfCRC;
};
struct {
uint8_t sysCmd;
uint8_t sysCmdData[7];
};
struct {
uint32_t metric1;
uint32_t metric2;
};
} datagram_t;
enum canState
{
stateUnknown,
MACLookup,
Idle,
StreamOpenedWrite,
StreamOpenedRead,
FrameRequested,
FrameReceived,
ReadConfig,
ConfigLoaded,
waitingConfirm,
Error
};
#pragma pack(pop)
class canDriver
{
public:
canDriver(){ready=false; controllerId=0; responseTimer=0; state=canState::stateUnknown;};
uint8_t getMyId();
bool sendStatus(uint16_t itemNum, itemCmd cmd, int subItem = NO_SUBITEM);
bool sendCommand(uint8_t devID, uint16_t itemID, itemCmd cmd, bool status=false, int subItemID=NO_SUBITEM );
bool sendCommand(aJsonObject * can,itemCmd cmd, bool status = false);
bool upTime(uint32_t ut);
bool salt(uint32_t salt);
bool lookupMAC();
bool requestFrame(uint8_t devId, payloadType _payloadType, uint16_t seqNo );
int readFrame();
bool sendRemoteID(macAddress mac);
bool begin();
void Poll();
bool processPacket(canid_t id, datagram_t *packet, uint8_t len, bool rtr=false);
bool write(uint32_t msg_id, datagram_t * buf = NULL, uint8_t size=0);
uint8_t getControllerID(){return controllerId;};
uint8_t getIdByMac(macAddress mac);
datagram_t RXpacket;
canid_t RXid;
uint8_t RXlen;
private:
aJsonObject * findConfbyID(uint8_t devId);
#if defined(ARDUINO_ARCH_STM32)
CAN_message_t CAN_RX_msg;
CAN_message_t CAN_TX_msg;
#endif
#if defined(__SAM3X8E__)
//CAN_FRAME CAN_RX_msg;
#endif
bool ready;
uint8_t controllerId;
canState state;
uint32_t responseTimer;
};
extern aJsonObject * topics;
class canStream : public Stream
{
public:
canStream(canDriver * _driver) : readPos(0),writePos(0),devId(0), pType(payloadType::unknown),state(canState::stateUnknown),seqNo(0),failedCount(0){driver=_driver; }
int open(uint8_t controllerID, payloadType _pType, char _mode)
{
if (mode) close();
devId=controllerID;
pType = _pType;
mode = _mode;
seqNo=0xFFFF;
failedCount=0;
if (mode == 'w') state=canState::StreamOpenedWrite;
else state=canState::StreamOpenedRead;
return 1;
};
int close ()
{
if ((mode == 'w') && writePos) flush();
mode = '\0';
state=canState::stateUnknown;
return 1;
}
// Stream methods
virtual int available();
virtual int read();
virtual int peek();
virtual void flush();
// Print methods
virtual size_t write(uint8_t c) ;
virtual int availableForWrite();
private:
int send(uint8_t len, uint16_t _seqNo);
int checkState();
canDriver * driver;
unsigned int readPos;
unsigned int writePos;
datagram_t writeBuffer;
uint8_t devId;
uint16_t seqNo;
int8_t failedCount;
char mode;
payloadType pType;
canState state;
//bool writeBlocked;
};
#endif //

View File

@@ -16,7 +16,7 @@ short colorChannel::getChannelAddr(short n)
return item->getArg(n); return item->getArg(n);
} }
/*
int colorChannel::getDefaultStorageType() int colorChannel::getDefaultStorageType()
{ {
@@ -33,7 +33,7 @@ int colorChannel::getDefaultStorageType()
return ST_VOID; return ST_VOID;
} }
/*
int colorChannel::isActive() int colorChannel::isActive()
{ {
itemCmd st; itemCmd st;
@@ -58,7 +58,6 @@ case S_NOTFOUND:
// turn on and set // turn on and set
toExecute = true; toExecute = true;
case S_SET: case S_SET:
//case S_ESET:
case S_HSV: case S_HSV:
PixelCtrl(cmd, subItem, toExecute, authorized); PixelCtrl(cmd, subItem, toExecute, authorized);
return 1; return 1;

View File

@@ -15,7 +15,7 @@ public:
numArgs = item->getArgCount(); // and how many addresses is configured numArgs = item->getArgCount(); // and how many addresses is configured
}; };
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized=false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized=false) override;
int getDefaultStorageType()override; //int getDefaultStorageType()override;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) =0; virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) =0;
short getChannelAddr(short n =0); short getChannelAddr(short n =0);
// int isActive() override; // int isActive() override;

View File

@@ -47,6 +47,7 @@ volatile uint32_t checkTimestamp=0L;
#if defined(_dmxin) #if defined(_dmxin)
volatile uint32_t D_State=0; volatile uint32_t D_State=0;
volatile unsigned long D_checkT=0; volatile unsigned long D_checkT=0;
uint8_t DMXINChannels=0;
#endif #endif
#ifdef _artnet #ifdef _artnet
@@ -61,6 +62,61 @@ extern aJsonObject *items;
extern aJsonObject *dmxArr; extern aJsonObject *dmxArr;
itemCmd rgb2hsv(itemCmd in)
{
itemCmd out;
out.setArgType(ST_HSV255);
double min, max, delta;
double inr=in.param.r/255;
double ing=in.param.g/255;
double inb=in.param.b/255;
double inw=in.param.w/255;
min = inr < ing ? inr : ing;
min = min < inb ? min : inb;
max = inr > ing ? inr : ing;
max = max > inb ? max : inb;
max = max > inw ? max : inw;
out.param.v = max*255; // v
delta = max - min;
if (delta < 0.00001)
{
out.param.s = 0;
out.param.h = 0; // undefined, maybe nan?
return out;
}
if( max > 0.0 ) { // NOTE: if Max is == 0, this divide would cause a crash
out.param.s = (delta / max)*100; // s
} else {
// if max is 0, then r = g = b = 0
// s = 0, h is undefined
out.param.s = 0;
out.param.h = 0; // its now undefined
return out;
}
double outh;
if( inr >= max ) // > is bogus, just keeps compilor happy
outh = ( ing - inb ) / delta; // between yellow & magenta
else
if( ing >= max )
outh = 2.0 + ( inb - inr ) / delta; // between cyan & yellow
else
outh = 4.0 + ( inr - ing ) / delta; // between magenta & cyan
outh *= 60.0; // degrees
if( outh < 0.0 )
outh += 360.0;
out.param.h=outh;
return out;
}
int itemCtrl2(char* name,int r,int g, int b, int w) int itemCtrl2(char* name,int r,int g, int b, int w)
{ {
if (!items) return 0; if (!items) return 0;
@@ -68,7 +124,6 @@ int itemCtrl2(char* name,int r,int g, int b, int w)
if (itemArr && (itemArr->type==aJson_Array)) if (itemArr && (itemArr->type==aJson_Array))
{ {
short itemtype = aJson.getArrayItem(itemArr,0)->valueint; short itemtype = aJson.getArrayItem(itemArr,0)->valueint;
short itemaddr = aJson.getArrayItem(itemArr,1)->valueint; short itemaddr = aJson.getArrayItem(itemArr,1)->valueint;
switch (itemtype){ switch (itemtype){
@@ -84,7 +139,6 @@ int itemCtrl2(char* name,int r,int g, int b, int w)
case CH_RGB: // RGB case CH_RGB: // RGB
{ {
DmxWrite(itemaddr, r); DmxWrite(itemaddr, r);
DmxWrite(itemaddr+1, g); DmxWrite(itemaddr+1, g);
DmxWrite(itemaddr+2, b); DmxWrite(itemaddr+2, b);
@@ -96,7 +150,7 @@ int itemCtrl2(char* name,int r,int g, int b, int w)
if (groupArr && (groupArr->type==aJson_Array)) if (groupArr && (groupArr->type==aJson_Array))
{ aJsonObject *i =groupArr->child; { aJsonObject *i =groupArr->child;
while (i) while (i)
{ //Serial.println(i->valuestring); {
if (i->type == aJson_String) itemCtrl2(i->valuestring,r,g,b,w); if (i->type == aJson_String) itemCtrl2(i->valuestring,r,g,b,w);
i=i->next;} i=i->next;}
} }
@@ -119,9 +173,34 @@ void DMXImmediateUpdate(short tch,short r, short g, short b, short w) {
} }
} }
void DMXSemiImmediateUpdate(short tch,short trh, int val) void DMXSemiImmediateUpdate(short tch,short r, short g, short b, short w)
{ {
//Here any code for passthrow between DMX IN and DMX OUT in idle state //Here any code for passthrow between DMX IN and DMX OUT in idle state
if (dmxArr && (dmxArr->type==aJson_Array))
{
aJsonObject *DMXch = aJson.getArrayItem(dmxArr,tch);
char* itemname = NULL;
if (DMXch->type == aJson_String) itemname=DMXch->valuestring;
if (itemname)
{
Item it(itemname);
if (!r && !g && !b && !w) it.Ctrl(itemCmd().Cmd(CMD_OFF).setSuffix(S_CMD));
else
{
/*
CRGB rgb;
rgb.r = r;
rgb.g = g;
rgb.b = b;
CHSV hsv = rgb2hsv_approximate(rgb);
it.Ctrl(itemCmd().HSV255(hsv.h,hsv.s,hsv.v).setSuffix(S_SET)); */
it.Ctrl(itemCmd().RGBW(r,g,b,w).setSuffix(S_SET));
//it.Ctrl(rgb2hsv(itemCmd().RGBW(r,g,b,w)).setSuffix(S_SET));
it.Ctrl(itemCmd().Cmd(CMD_ON).setSuffix(S_CMD));
}
}
}
} }
void DMXput(void) void DMXput(void)
@@ -132,6 +211,7 @@ for (short tch=0; tch<=3 ; tch++)
short base = tch*4; short base = tch*4;
DMXImmediateUpdate(tch,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]); DMXImmediateUpdate(tch,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]);
} }
}; };
extern volatile uint8_t timerHandlerBusy; extern volatile uint8_t timerHandlerBusy;
@@ -140,81 +220,62 @@ extern volatile uint8_t timerHandlerBusy;
volatile int DMXinDoublecheck=0; volatile int DMXinDoublecheck=0;
#endif #endif
// INVOKED BY INTERRUPTS - MUST BE SAFE CODE
void DMXUpdate(void) void DMXUpdate(void)
{ {
#if defined(_dmxin) #if defined(_dmxin)
int t;
if(!DMXin) return; if(!DMXin) return;
#if defined(__SAM3X8E__) #if defined(__SAM3X8E__)
if (dmxin.getRxLength()<16) return; if (dmxin.getRxLength()<DMXINChannels) return;
#endif #endif
for (short tch=0; tch<=3 ; tch++)
uint8_t RGBWChannels=DMXINChannels >> 2;
for (short tch=0; tch<RGBWChannels ; tch++)
{ {
short base = tch*4; short base = tch*4;
bool updated = 0; bool updated = false;
bool confirmed = 0; int t;
for (short trh=0; trh<4 ; trh++) for (short trh=0; trh<4 ; trh++)
if (((t=dmxin.read(base+trh+1)) != DMXin[base+trh])) if ((t=dmxin.read(base+trh+1)) != DMXin[base+trh])
{
updated=1;
if (DMXinDoublecheck>2)
{ {
D_State |= (1<<tch); D_State |= (1<<tch);
updated=1;
DMXin[base+trh]=t; DMXin[base+trh]=t;
confirmed = 1;
} }
} if (updated)
if (updated) DMXinDoublecheck++; else DMXinDoublecheck=0;
if (confirmed)
{ {
DMXImmediateUpdate(tch,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]); DMXImmediateUpdate(tch,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]);
//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print("-");};debugSerial.print("|");
D_checkT=millisNZ(); D_checkT=millisNZ();
} }
} }
//Serial.print(D_State,BIN);Serial.println();
#endif #endif
} }
// INVOKED in safe loop
void DMXCheck(void) void DMXCheck(void)
{ {
// CHSV hsv;
// CRGB rgb;
DMXOUT_propagate(); DMXOUT_propagate();
#if defined(_dmxin) #if defined(_dmxin)
short t,tch;
//Here code for semi-immediate update
for (t=1,tch=0; t<=8 ; t<<=1,tch++)
if (D_State & t)
{
// Serial.print(D_State,BIN);Serial.print(":");
D_State &= ~t;
for (short trh=0; trh<4 ; trh++)
DMXSemiImmediateUpdate(tch,trh,DMXin[tch*4+trh]);
}
//if ((millis()<D_checkT) || (D_checkT==0)) return;
if ( (!D_checkT) || (!isTimeOver(D_checkT,millis(),D_CHECKT))) return; if ( (!D_checkT) || (!isTimeOver(D_checkT,millis(),D_CHECKT))) return;
D_checkT=0; D_checkT=0;
uint8_t RGBWChannels=DMXINChannels >> 2;
for (short rgbwChan=0; rgbwChan < RGBWChannels; rgbwChan++)
{
short base = rgbwChan*4;
short bitMask = 1 << rgbwChan;
if (D_State & bitMask)
{
D_State &= ~bitMask;
DMXSemiImmediateUpdate(rgbwChan,DMXin[base],DMXin[base+1],DMXin[base+2],DMXin[base+3]);
break;
}
}
// Here code for network update //#ifdef _dmxout
//int ch = 0; //for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
//debugSerial.println();
DMXput(); //#endif
#ifdef _dmxout
for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
debugSerial.println();
#endif
#endif #endif
} }
@@ -238,7 +299,9 @@ void DMXinSetup(int channels)
//DmxSimple.maxChannel(channels); //DmxSimple.maxChannel(channels);
#if defined(_dmxin) #if defined(_dmxin)
if (channels>(32*4)) channels = 32*4;
DMXin = new uint8_t [channels]; DMXin = new uint8_t [channels];
DMXINChannels=channels;
#if defined(ARDUINO_ARCH_AVR) #if defined(ARDUINO_ARCH_AVR)
DMXSerial.init(DMXReceiver,0,channels); DMXSerial.init(DMXReceiver,0,channels);
if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err")); if (DMXSerial.getBuffer()) {debugSerial.print(F("Init in ch:"));debugSerial.println(channels);} else debugSerial.println(F("DMXin Buffer alloc err"));

View File

@@ -56,7 +56,7 @@ unsigned int startPos;
char openmode ; char openmode ;
public: public:
flashStream():seekableStream(MAX_STREAM_SIZE){openmode = '\0';}; flashStream():seekableStream(MAX_STREAM_SIZE),pos(0),startPos(0),openmode('\0'){};
void setSize(unsigned int _size); void setSize(unsigned int _size);
int open(short fileNum, char mode='\0') ; int open(short fileNum, char mode='\0') ;
virtual int open(String _filename, char mode='\0') override; virtual int open(String _filename, char mode='\0') override;

View File

@@ -21,7 +21,9 @@ e-mail anklimov@gmail.com
#include "inputs.h" #include "inputs.h"
#include "item.h" #include "item.h"
#include "utils.h" #include "utils.h"
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
#endif
#include "main.h" #include "main.h"
#include "itemCmd.h" #include "itemCmd.h"
@@ -33,12 +35,26 @@ e-mail anklimov@gmail.com
#endif #endif
#endif #endif
#ifdef CANDRV
#include <candriver.h>
extern canDriver LHCAN;
#endif
#ifdef MCP23017 #ifdef MCP23017
#include "Adafruit_MCP23X17.h" #include "Adafruit_MCP23X17.h"
Adafruit_MCP23X17 mcp; Adafruit_MCP23X17 mcp;
#endif #endif
#ifdef ULTRASONIC
#define US_TRIG PA_14 //pin49
#define US_ECHO PA_15 //pin50
#include "Ultrasonic.h"
Ultrasonic ultrasonic(US_TRIG, US_ECHO);
#endif
#if not defined (NOIP)
extern PubSubClient mqttClient; extern PubSubClient mqttClient;
#endif
extern aJsonObject *root; extern aJsonObject *root;
extern int8_t ethernetIdleCount; extern int8_t ethernetIdleCount;
extern int8_t configLocked; extern int8_t configLocked;
@@ -99,6 +115,7 @@ void Input::Parse(aJsonObject * configObj)
store = NULL; store = NULL;
inType = 0; inType = 0;
pin = 0; pin = 0;
pin2 =0;
if (!inputObj || !root) return; if (!inputObj || !root) return;
if (!configObj) configObj = inputObj; if (!configObj) configObj = inputObj;
@@ -110,10 +127,25 @@ void Input::Parse(aJsonObject * configObj)
if (itemBuffer) inType = static_cast<uint8_t>(itemBuffer->valueint); if (itemBuffer) inType = static_cast<uint8_t>(itemBuffer->valueint);
itemBuffer = aJson.getObjectItem(configObj, "#"); itemBuffer = aJson.getObjectItem(configObj, "#");
if (itemBuffer) pin = static_cast<uint8_t>(itemBuffer->valueint); if (itemBuffer)
else pin = static_cast<uint8_t>(atoi(configObj->name)); switch (itemBuffer->type)
{
case aJson_Int:
pin = static_cast<uint8_t>(itemBuffer->valueint);
break;
case aJson_Array:
if ((itemBuffer->child) && (itemBuffer->child->type == aJson_Int))
{
pin = static_cast<uint8_t>(itemBuffer->child->valueint);
if ((itemBuffer->child->child) && (itemBuffer->child->child->type == aJson_Int))
pin = static_cast<uint8_t>(itemBuffer->child->child->valueint);
} }
} //switch
else pin = static_cast<uint8_t>(atoi(configObj->name));
}
// Persistant storage // Persistant storage
itemBuffer = aJson.getObjectItem(inputObj, "@S"); itemBuffer = aJson.getObjectItem(inputObj, "@S");
if (!itemBuffer) { if (!itemBuffer) {
@@ -127,8 +159,10 @@ void Input::Parse(aJsonObject * configObj)
void cleanStore(aJsonObject * input) void cleanStore(aJsonObject * input)
{ {
if (input->type == aJson_Object) { if (input && (input->type == aJson_Object)) {
// Check for nested inputs // Check for nested inputs
Input in(input);
in.store->aslong = 0;
aJsonObject * inputArray = aJson.getObjectItem(input, "act"); aJsonObject * inputArray = aJson.getObjectItem(input, "act");
if (inputArray && (inputArray->type == aJson_Array)) if (inputArray && (inputArray->type == aJson_Array))
{ {
@@ -145,8 +179,8 @@ if (input->type == aJson_Object) {
} }
else else
{ {
Input in(input); // Input in(input);
in.Poll(CHECK_INPUT); // in.store->aslong = 0;
} }
} }
} }
@@ -258,6 +292,14 @@ switch (cause) {
break; break;
} }
break; break;
case CHECK_ULTRASONIC:
switch (inType)
{
case IN_ULTRASONIC:
analogPoll(cause);
contactPoll(cause);
}
break;
case CHECK_SENSOR: //Slow polling case CHECK_SENSOR: //Slow polling
switch (inType) switch (inType)
{ {
@@ -519,12 +561,13 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
#endif #endif
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause // TODO Polling via timed interrupt with CHECK_INTERRUPT cause
bool Input::changeState(uint8_t newState, short cause) bool Input::
changeState(uint8_t newState, short cause)
{ {
if (!inputObj || !store) return false; if (!inputObj || !store) return false;
if (newState == IS_REQSTATE) if (newState == IS_REQSTATE)
if (store->delayedState && cause != CHECK_INTERRUPT) if (store->delayedState && (cause != CHECK_INTERRUPT))
{ {
// Requested delayed change State and safe moment // Requested delayed change State and safe moment
newState=store->reqState; //Retrieve requested state newState=store->reqState; //Retrieve requested state
@@ -622,6 +665,7 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
aJsonObject *defaultItem = aJson.getObjectItem(inputObj, "item"); aJsonObject *defaultItem = aJson.getObjectItem(inputObj, "item");
aJsonObject *defaultEmit = aJson.getObjectItem(inputObj, "emit"); aJsonObject *defaultEmit = aJson.getObjectItem(inputObj, "emit");
aJsonObject *defaultCan = aJson.getObjectItem(inputObj, "can");
if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID); if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID);
@@ -637,7 +681,7 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
{ {
store->state=newState; store->state=newState;
store->delayedState=false; store->delayedState=false;
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit); executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
return true; return true;
} }
else else
@@ -656,8 +700,11 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
static volatile uint8_t contactPollBusy = 0; static volatile uint8_t contactPollBusy = 0;
void Input::contactPoll(short cause) { void Input::contactPoll(short cause) {
boolean currentInputState; bool currentInputState;
if (!store /*|| contactPollBusy*/) return; if (!store /*|| contactPollBusy*/) return;
if ((inType == IN_ULTRASONIC) && (cause!=CHECK_ULTRASONIC)) return;
contactPollBusy++; contactPollBusy++;
changeState(IS_REQSTATE,cause); //Check for postponed states transitions changeState(IS_REQSTATE,cause); //Check for postponed states transitions
@@ -674,9 +721,9 @@ if (inType & IN_I2C)
currentInputState = (inCache.I2CReadBit(IN_I2C,0,pin) == inputOnLevel); currentInputState = (inCache.I2CReadBit(IN_I2C,0,pin) == inputOnLevel);
else else
#endif #endif
if (isAnalogPin(pin) && (mapObj=aJson.getObjectItem(inputObj, "map")) && mapObj->type == aJson_Array) if ((isAnalogPin(pin) || (inType == IN_ULTRASONIC)) && (mapObj=aJson.getObjectItem(inputObj, "map")) && mapObj->type == aJson_Array)
{ {
int value = inCache.analogReadCached(pin); int value = inCache.analogReadCached(pin,pin2,inType);
if (value >= aJson.getArrayItem(mapObj, 0)->valueint && value <= aJson.getArrayItem(mapObj, 1)->valueint) if (value >= aJson.getArrayItem(mapObj, 0)->valueint && value <= aJson.getArrayItem(mapObj, 1)->valueint)
currentInputState = true; currentInputState = true;
else currentInputState = false; else currentInputState = false;
@@ -886,7 +933,7 @@ void Input::analogPoll(short cause) {
pinMode(pin, inputPinMode); pinMode(pin, inputPinMode);
*/ */
inputVal = inCache.analogReadCached(pin); inputVal = inCache.analogReadCached(pin,pin2,inType);
// Mapping // Mapping
if (inputMap && inputMap->type == aJson_Array) if (inputMap && inputMap->type == aJson_Array)
{ {
@@ -950,7 +997,8 @@ void Input::onContactChanged(int newValue) {
aJsonObject *item = aJson.getObjectItem(inputObj, "item"); aJsonObject *item = aJson.getObjectItem(inputObj, "item");
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit"); aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
if (!item && !emit) return; aJsonObject *can = aJson.getObjectItem(inputObj, "can");
if (!item && !emit && !can) return;
aJsonObject *scmd = aJson.getObjectItem(inputObj, "scmd"); aJsonObject *scmd = aJson.getObjectItem(inputObj, "scmd");
aJsonObject *rcmd = aJson.getObjectItem(inputObj, "rcmd"); aJsonObject *rcmd = aJson.getObjectItem(inputObj, "rcmd");
debugSerial << F("LEGACY IN:") << (pin) << F("=") << newValue << endl; debugSerial << F("LEGACY IN:") << (pin) << F("=") << newValue << endl;
@@ -965,6 +1013,7 @@ void Input::onContactChanged(int newValue) {
} else } else
#endif #endif
{ {
#if not defined (NOIP)
char addrstr[MQTT_TOPIC_LENGTH]; char addrstr[MQTT_TOPIC_LENGTH];
strncpy(addrstr,emit->valuestring,sizeof(addrstr)); strncpy(addrstr,emit->valuestring,sizeof(addrstr));
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
@@ -979,6 +1028,7 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true); else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true);
} }
} }
#endif //NOIP
} }
} // emit } // emit
if (item && item->type == aJson_String) { if (item && item->type == aJson_String) {
@@ -996,6 +1046,22 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
} }
} }
} }
#ifdef CANDRV
if (can)
{
if (newValue) { //send set command
if (!scmd || scmd->type != aJson_String) LHCAN.sendCommand(can,itemCmd(ST_VOID,CMD_ON));
else if (strlen(scmd->valuestring)) LHCAN.sendCommand(can,itemCmd(scmd->valuestring));
} else { //send reset command
if (!rcmd || rcmd->type != aJson_String) LHCAN.sendCommand(can,itemCmd(ST_VOID,CMD_OFF));
else if (strlen(rcmd->valuestring)) LHCAN.sendCommand(can,itemCmd(rcmd->valuestring));
}
}
#endif
} }
@@ -1009,8 +1075,7 @@ void Input::onAnalogChanged(itemCmd newValue) {
// Legacy // Legacy
aJsonObject *item = aJson.getObjectItem(inputObj, "item"); aJsonObject *item = aJson.getObjectItem(inputObj, "item");
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit"); aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
#if not defined (NOIP)
if (emit && emit->type == aJson_String) { if (emit && emit->type == aJson_String) {
//#ifdef WITH_DOMOTICZ //#ifdef WITH_DOMOTICZ
@@ -1028,11 +1093,18 @@ void Input::onAnalogChanged(itemCmd newValue) {
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
mqttClient.publish(addrstr, strVal, true); mqttClient.publish(addrstr, strVal, true);
} }
#endif //NOIP
if (item && item->type == aJson_String) { if (item && item->type == aJson_String) {
Item it(item->valuestring); Item it(item->valuestring);
if (it.isValid()) it.Ctrl(newValue); if (it.isValid()) it.Ctrl(newValue);
} }
#ifdef CANDRV
aJsonObject *can = aJson.getObjectItem(inputObj, "can");
if (can) LHCAN.sendCommand(can, newValue);
#endif
} }
@@ -1072,10 +1144,21 @@ readCache::readCache()
{ {
addr=0; addr=0;
type=0; type=0;
cached_data = 0;
} }
uint16_t readCache::analogReadCached (uint8_t _pin) uint16_t readCache::analogReadCached (uint8_t _pin, uint8_t trigPin, uint8_t _type )
{ {
#ifdef ULTRASONIC
if (_type == IN_ULTRASONIC)
{
if ((_pin==addr) && (IN_ULTRASONIC == type)) return cached_data;
type = IN_ULTRASONIC;
cached_data=ultrasonic.read();
//debugSerial<<F("LEN: ")<<cached_data<<endl;
return cached_data;
}
#endif
if ((_pin==addr) && (IN_ANALOG==type)) return cached_data; if ((_pin==addr) && (IN_ANALOG==type)) return cached_data;
addr = _pin; addr = _pin;
type = IN_ANALOG; type = IN_ANALOG;

View File

@@ -33,6 +33,7 @@ e-mail anklimov@gmail.com
#define IN_DHT22 4 #define IN_DHT22 4
#define IN_CCS811 5 #define IN_CCS811 5
#define IN_HDC1080 6 #define IN_HDC1080 6
#define IN_ULTRASONIC 7
#define IN_COUNTER 8 #define IN_COUNTER 8
#define IN_UPTIME 16 #define IN_UPTIME 16
@@ -62,6 +63,7 @@ e-mail anklimov@gmail.com
#define CHECK_SENSOR 1 #define CHECK_SENSOR 1
#define CHECK_INPUT 2 #define CHECK_INPUT 2
#define CHECK_INTERRUPT 3 #define CHECK_INTERRUPT 3
#define CHECK_ULTRASONIC 4
#define T_LONG 1000 #define T_LONG 1000
@@ -105,7 +107,7 @@ extern aJsonObject *inputs;
typedef union { typedef union {
long int aslong; uint32_t aslong;
uint32_t timestamp; uint32_t timestamp;
// Analog input structure // Analog input structure
struct { struct {
@@ -134,6 +136,7 @@ public:
aJsonObject *inputObj; aJsonObject *inputObj;
uint8_t inType; uint8_t inType;
uint8_t pin; uint8_t pin;
uint8_t pin2;
inStore *store; inStore *store;
Input(aJsonObject *obj, aJsonObject * configObj = NULL); Input(aJsonObject *obj, aJsonObject * configObj = NULL);
@@ -188,11 +191,12 @@ protected:
class readCache { class readCache {
public: public:
readCache(); readCache();
uint16_t analogReadCached (uint8_t pin); uint16_t analogReadCached (uint8_t pin, uint8_t trigPin=0, uint8_t _type = IN_ANALOG);
uint8_t digitalReadCached(uint8_t pin); uint8_t digitalReadCached(uint8_t pin);
#ifdef MCP23017 #ifdef MCP23017
uint8_t I2CReadBit(uint8_t type, uint8_t addr, uint8_t pin); uint8_t I2CReadBit(uint8_t type, uint8_t addr, uint8_t pin);
#endif #endif
void invalidateInputCache(); void invalidateInputCache();
protected: protected:
uint8_t addr; uint8_t addr;

View File

@@ -26,6 +26,7 @@ e-mail anklimov@gmail.com
#include "main.h" #include "main.h"
#include "bright.h" #include "bright.h"
#include "itemCmd.h" #include "itemCmd.h"
#include "candriver.h"
//#include "SHA256.h" //#include "SHA256.h"
#ifdef _dmxout #ifdef _dmxout
@@ -40,8 +41,9 @@ e-mail anklimov@gmail.com
#ifndef MODBUS_DISABLE #ifndef MODBUS_DISABLE
#include <ModbusMaster.h> #include <ModbusMaster.h>
#endif #endif
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
#endif
#include "modules/out_spiled.h" #include "modules/out_spiled.h"
#include "modules/out_ac.h" #include "modules/out_ac.h"
#include "modules/out_motor.h" #include "modules/out_motor.h"
@@ -66,11 +68,18 @@ e-mail anklimov@gmail.com
#include "modules/out_humidifier.h" #include "modules/out_humidifier.h"
#endif #endif
#ifdef CANDRV
#include <candriver.h>
extern canDriver LHCAN;
#endif
short modbusBusy = 0; short modbusBusy = 0;
//bool isPendedModbusWrites = false; //bool isPendedModbusWrites = false;
extern aJsonObject *pollingItem; extern aJsonObject *pollingItem;
#if not defined (NOIP)
extern PubSubClient mqttClient; extern PubSubClient mqttClient;
#endif
extern int8_t ethernetIdleCount; extern int8_t ethernetIdleCount;
extern int8_t configLocked; extern int8_t configLocked;
extern lan_status lanStatus; extern lan_status lanStatus;
@@ -104,8 +113,15 @@ int subitem2cmd(char *payload) {
} }
int txt2subItem(char *payload) { int txt2subItem(char *payload) {
int cmd = S_NOTFOUND;
if (!payload || !strlen(payload)) return S_NOTFOUND; if (!payload || !strlen(payload)) return S_NOTFOUND;
for(uint8_t i=1; i<suffixNum ;i++)
if (strcmp_P(payload, suffix_P[i]) == 0)
{
return i;
}
return S_NOTFOUND;
/*
int cmd = S_NOTFOUND;
// Check for command // Check for command
if (strcmp_P(payload, SET_P) == 0) cmd = S_SET; if (strcmp_P(payload, SET_P) == 0) cmd = S_SET;
else if (strcmp_P(payload, CTRL_P) == 0) cmd = S_CTRL; else if (strcmp_P(payload, CTRL_P) == 0) cmd = S_CTRL;
@@ -120,13 +136,15 @@ int txt2subItem(char *payload) {
else if (strcmp_P(payload, VAL_P) == 0) cmd = S_VAL; else if (strcmp_P(payload, VAL_P) == 0) cmd = S_VAL;
else if (strcmp_P(payload, DEL_P) == 0) cmd = S_DELAYED; else if (strcmp_P(payload, DEL_P) == 0) cmd = S_DELAYED;
else if (strcmp_P(payload, _RAW_P) == 0) cmd = S_RAW; else if (strcmp_P(payload, _RAW_P) == 0) cmd = S_RAW;
return cmd; return cmd; */
} }
//const short defval[4] = {0, 0, 0, 0}; //Type,Arg,Val,Cmd //const short defval[4] = {0, 0, 0, 0}; //Type,Arg,Val,Cmd
Item::Item(aJsonObject *obj)//Constructor Item::Item(aJsonObject *obj, aJsonObject *_items)//Constructor
{ {
rootItems=_items;
itemArr = obj; itemArr = obj;
driver = NULL; driver = NULL;
*defaultSubItem = 0; *defaultSubItem = 0;
@@ -275,13 +293,14 @@ Item::~Item()
} }
} }
Item::Item(char *name) //Constructor Item::Item(char *name, aJsonObject *_items) //Constructor
{ {
char * pDefaultSubItem = defaultSubItem; char * pDefaultSubItem = defaultSubItem;
rootItems=_items;
driver = NULL; driver = NULL;
defaultSubItem[0] =0; defaultSubItem[0] =0;
defaultSuffixCode = 0; defaultSuffixCode = 0;
if (name && items) if (name && rootItems)
{ char* sub; { char* sub;
if (sub=strchr(name,'/')) if (sub=strchr(name,'/'))
{ {
@@ -290,7 +309,7 @@ Item::Item(char *name) //Constructor
for(i=0;(name[i] && (name[i]!='/') && (i<MQTT_SUBJECT_LENGTH));i++) for(i=0;(name[i] && (name[i]!='/') && (i<MQTT_SUBJECT_LENGTH));i++)
buf[i]=name[i]; buf[i]=name[i];
buf[i]=0; buf[i]=0;
itemArr = aJson.getObjectItem(items, buf); itemArr = aJson.getObjectItem(rootItems, buf);
sub++; sub++;
strncpy(defaultSubItem,sub,sizeof(defaultSubItem)-1); strncpy(defaultSubItem,sub,sizeof(defaultSubItem)-1);
defaultSuffixCode = retrieveCode (&pDefaultSubItem); defaultSuffixCode = retrieveCode (&pDefaultSubItem);
@@ -298,13 +317,107 @@ Item::Item(char *name) //Constructor
//debugSerial<<F("defaultSubItem: ")<<defaultSubItem<<F(" defaultSuffixCode:")<<defaultSuffixCode<<endl; //debugSerial<<F("defaultSubItem: ")<<defaultSubItem<<F(" defaultSuffixCode:")<<defaultSuffixCode<<endl;
} }
else else
itemArr = aJson.getObjectItem(items, name); itemArr = aJson.getObjectItem(rootItems, name);
} }
else itemArr = NULL; else itemArr = NULL;
Parse(); Parse();
} }
uint16_t getCanNum(aJsonObject* verb)
{
if (!verb) return 0;
switch (verb->type)
{
case aJson_Array:
{
aJsonObject *canNumObj=aJson.getArrayItem(verb,1);
if (canNumObj->type == aJson_Int) return canNumObj->valueint;
return 0;
}
case aJson_Object:
{
aJsonObject *canNumObj=aJson.getObjectItem(verb, "can");
if (canNumObj->type == aJson_Int) return canNumObj->valueint;
return 0;
}
}
return 0;
}
char * Item::getSubItemStrById(uint8_t subItem)
{
if (subItem == NO_SUBITEM) return NULL;
if (!itemArg) return NULL;
aJsonObject * i = itemArg;
if (i->type == aJson_Array) i=i->child;
while (i)
{
if (i->type == aJson_Object)
{
aJsonObject * s = aJson.getArrayItem(i,subItem);
if (s && (s->type == aJson_Object)) return s->name;
return NULL;
}
i=i->next;
}
return NULL;
};
uint8_t Item::getSubitemId(char * subItem)
{
if (!subItem) return NO_SUBITEM;
if (!itemArg) return NO_SUBITEM;
aJsonObject * i = itemArg;
if (i->type == aJson_Array) i=i->child;
while (i)
{
if (i->type == aJson_Object)
{
aJsonObject *c = i->child;
uint8_t index=0;
while (c)
{
if (!strcasecmp(c->name, subItem)) return index;
c = c->next; index++;
}
return NO_SUBITEM;
}
i=i->next;
};
return NO_SUBITEM;
}
Item::Item(uint16_t num, uint8_t subItem, aJsonObject *_items)
{
itemArr = NULL;
itemArg = NULL;
itemVal = NULL;
itemExt = NULL;
rootItems=_items;
driver = NULL;
defaultSubItem[0] =0;
defaultSuffixCode = 0;
if (!rootItems) return;
itemArr = rootItems->child;
if (!num) return;
while (itemArr)
{
if (getCanNum(itemArr->child) == num)
{
debugSerial<<"Find item: "<< itemArr->name << " addr:" << num << endl;
Parse();
char * subItemStr = getSubItemStrById(subItem);
if (subItemStr) strncpy(defaultSubItem,subItemStr,sizeof(defaultSubItem));
return;
}
itemArr = itemArr->next;
}
}
uint8_t Item::getCmd() { uint8_t Item::getCmd() {
aJsonObject *t = aJson.getArrayItem(itemArr, I_CMD); aJsonObject *t = aJson.getArrayItem(itemArr, I_CMD);
if (t) if (t)
@@ -319,7 +432,7 @@ void Item::setCmd(uint8_t cmdValue) {
{ {
itemCmd->type = aJson_Int; itemCmd->type = aJson_Int;
itemCmd->valueint = cmdValue & CMD_MASK | itemCmd->valueint & (FLAG_MASK); // Preserve special bits itemCmd->valueint = cmdValue & CMD_MASK | itemCmd->valueint & (FLAG_MASK); // Preserve special bits
debugSerial<<F("SetCmd:")<<cmdValue<<endl; //debugSerial<<F("SetCmd:")<<cmdValue<<endl;
} }
} }
@@ -487,7 +600,7 @@ void Item::setExt(long int par) // Only store if VAL is int (autogenerated or c
if(itemExt->type == aJson_NULL) itemExt->type=aJson_Int; if(itemExt->type == aJson_NULL) itemExt->type=aJson_Int;
else if(itemExt->type != aJson_Int ) return; else if(itemExt->type != aJson_Int ) return;
itemExt->valueint = par; itemExt->valueint = par;
debugSerial<<F("Stored EXT:")<<par<<endl; //debugSerial<<F("Stored EXT:")<<par<<endl;
} }
@@ -577,7 +690,7 @@ if (!payload) return 0;
int fr = freeRam(); int fr = freeRam();
if (fr < minimalMemory) if (fr < minimalMemory)
{ {
errorSerial<<F("CTRL/txt: OutOfMemory: ")<<fr<<endl; errorSerial<<F("MQTT: CTRL/txt: OutOfMemory: ")<<fr<<endl;
return -1; return -1;
} }
@@ -639,7 +752,7 @@ st.setSuffix(suffixCode);
int Par[3]; int Par[3];
while (payload && k < 3) while (payload && k < 3)
Par[k++] = getInt((char **) &payload); Par[k++] = getIntFromStr((char **) &payload);
i=i+k; //i=total # of parameters i=i+k; //i=total # of parameters
switch(suffixCode) switch(suffixCode)
{case S_HUE: {case S_HUE:
@@ -684,7 +797,7 @@ st.setSuffix(suffixCode);
short i = 0; short i = 0;
int Par[4]; int Par[4];
while (payload && i < 4) while (payload && i < 4)
Par[i++] = getInt((char **) &payload); Par[i++] = getIntFromStr((char **) &payload);
switch (i) //Number of params switch (i) //Number of params
{ {
@@ -706,7 +819,7 @@ st.setSuffix(suffixCode);
} }
default: //some known command default: //some known command
{ {
int32_t intParam = getInt((char **) &payload); int32_t intParam = getIntFromStr((char **) &payload);
if (intParam) st.Int(intParam); if (intParam) st.Int(intParam);
return Ctrl(st,NULL, true, authorized); return Ctrl(st,NULL, true, authorized);
} }
@@ -717,7 +830,7 @@ return 0;
// Recursive function with small stack consumption // Recursive function with small stack consumption
// if cmd defined - execute Ctrl for any group members recursively // if cmd defined - execute Ctrl for any group members recursively
// else performs Activity check for group members and return true if any member is active // else performs Activity check for group members and return true if any member is active
bool digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized) bool Item::digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorized)
{ if (!itemArr || itemArr->type!=aJson_Array) return false; { if (!itemArr || itemArr->type!=aJson_Array) return false;
// Iterate across array of names // Iterate across array of names
aJsonObject *i = itemArr->child; aJsonObject *i = itemArr->child;
@@ -725,7 +838,7 @@ bool digGroup (aJsonObject *itemArr, itemCmd *cmd, char* subItem, bool authorize
while (i) { while (i) {
if (i->type == aJson_String) if (i->type == aJson_String)
{ //debugSerial<< i->valuestring<<endl; { //debugSerial<< i->valuestring<<endl;
aJsonObject *nextItem = aJson.getObjectItem(items, i->valuestring); aJsonObject *nextItem = aJson.getObjectItem(rootItems, i->valuestring);
if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item if (nextItem && nextItem->type == aJson_Array) //nextItem is correct item
{ {
Item it(nextItem); Item it(nextItem);
@@ -908,6 +1021,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
int res = -1; int res = -1;
uint16_t status2Send = 0; uint16_t status2Send = 0;
uint8_t command2Set = 0; uint8_t command2Set = 0;
itemCmd originalCmd = cmd;
/// Common (GRP & NO GRP) commands /// Common (GRP & NO GRP) commands
switch (cmd.getCmd()) switch (cmd.getCmd())
@@ -1063,7 +1177,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
if ((suffixCode==S_CMD) && cmd.isValue()) if ((suffixCode==S_CMD) && cmd.isValue())
{ {
scheduleOppositeCommand(cmd,chActive,authorized); scheduleOppositeCommand(originalCmd,chActive,authorized);
scheduledOppositeCommand = true; scheduledOppositeCommand = true;
} }
} }
@@ -1372,7 +1486,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion, bool authorized
if (oppositeCommandToBeSchedulled) //invoked not as group part, delayed if (oppositeCommandToBeSchedulled) //invoked not as group part, delayed
{ {
scheduleOppositeCommand(cmd,chActive,authorized); scheduleOppositeCommand(originalCmd,chActive,authorized);
status2Send &=~FLAG_PARAMETERS; status2Send &=~FLAG_PARAMETERS;
} }
} // NO GROUP } // NO GROUP
@@ -1461,10 +1575,16 @@ if ((!driver || driver->isAllowed(cmd)) && (!getFlag(FLAG_FREEZED)))
{ {
thermostatStore tStore; thermostatStore tStore;
tStore.asint=getExt(); tStore.asint=getExt();
if (!tStore.timestamp16) mqttClient.publish("/alarmoff/snsr", itemArr->name); if (!tStore.timestamp16)
{
infoSerial<<F("Cleaning alarm ")<<itemArr->name<<endl;
#if not defined (NOIP)
mqttClient.publish("/alarmoff/snsr", itemArr->name);
#endif
}
tStore.tempX100=cmd.getFloat()*100.; //Save measurement tStore.tempX100=cmd.getFloat()*100.; //Save measurement
tStore.timestamp16=millisNZ(8) & 0xFFFF; //And timestamp tStore.timestamp16=millisNZ(8) & 0xFFFF; //And timestamp
debugSerial<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl; debugSerial<<F("THERM:")<<itemArr->name<<F(" T:")<<tStore.tempX100<<F(" TS:")<<tStore.timestamp16<<endl;
setExt(tStore.asint); setExt(tStore.asint);
res=1; res=1;
} }
@@ -1707,7 +1827,6 @@ int Item::SendStatus(int sendFlags) {
itemCmd st(ST_VOID,CMD_VOID); itemCmd st(ST_VOID,CMD_VOID);
st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS); st.loadItem(this, FLAG_COMMAND | FLAG_PARAMETERS);
sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS); //if some delayed status is pending sendFlags |= getFlag(FLAG_COMMAND | FLAG_PARAMETERS | FLAG_FLAGS); //if some delayed status is pending
//debugSerial<<F("ssi:")<<sendFlags<<endl;
return SendStatusImmediate(st,sendFlags); return SendStatusImmediate(st,sendFlags);
} }
} }
@@ -1717,8 +1836,14 @@ int Item::SendStatus(int sendFlags) {
char addrstr[64]; char addrstr[64];
char valstr[20] = ""; char valstr[20] = "";
char cmdstr[9] = ""; char cmdstr[9] = "";
//debugSerial<<"SSI "<<subItem<<endl;
debugSerial<<"SENDSTATUS: "<<subItem;
st.debugOut(); st.debugOut();
#ifdef CANDRV
if (!(sendFlags & FLAG_NOT_SEND_CAN)) LHCAN.sendStatus(getCanNum(itemArr->child),st, getSubitemId(subItem));
#endif
if (sendFlags & FLAG_COMMAND) if (sendFlags & FLAG_COMMAND)
{ {
// Preparing legacy Command payload ////////////// // Preparing legacy Command payload //////////////
@@ -1745,7 +1870,7 @@ int Item::SendStatus(int sendFlags) {
break; break;
default: default:
debugSerial<<F("Unknown cmd \n"); debugSerial<<F("SENDSTATUS: Unknown cmd \n");
sendFlags &= ~FLAG_COMMAND; sendFlags &= ~FLAG_COMMAND;
} }
} }
@@ -1753,7 +1878,7 @@ int Item::SendStatus(int sendFlags) {
// publish to MQTT - OpenHab Legacy style to // publish to MQTT - OpenHab Legacy style to
// myhome/s_out/item - mix: value and command // myhome/s_out/item - mix: value and command
#if not defined (NOIP)
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
if (!subItem ) if (!subItem )
@@ -1778,6 +1903,7 @@ int Item::SendStatus(int sendFlags) {
} }
} //!subItem } //!subItem
} }
#endif //NOIP
else else
{ {
setFlag(sendFlags); setFlag(sendFlags);
@@ -1801,9 +1927,14 @@ int Item::SendStatus(int sendFlags) {
strncat(addrstr, "/", sizeof(addrstr)-1); strncat(addrstr, "/", sizeof(addrstr)-1);
// if (sendFlags & FLAG_SEND_DELAYED)
// strncat_P(addrstr, DEL_P, sizeof(addrstr)-1);
// else strncat_P(addrstr, SET_P, sizeof(addrstr)-1);
if (sendFlags & FLAG_SEND_DELAYED) if (sendFlags & FLAG_SEND_DELAYED)
strncat_P(addrstr, DEL_P, sizeof(addrstr)-1); strncat_P(addrstr, suffix_P[S_DELAYED], sizeof(addrstr)-1);
else strncat_P(addrstr, SET_P, sizeof(addrstr)-1); else strncat_P(addrstr, suffix_P[S_SET], sizeof(addrstr)-1);
// Preparing parameters payload ////////// // Preparing parameters payload //////////
switch (st.getArgType()) { switch (st.getArgType()) {
@@ -1821,6 +1952,7 @@ int Item::SendStatus(int sendFlags) {
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl; debugSerial<<F("Pub: ")<<addrstr<<F("->")<<valstr<<endl;
#if not defined (NOIP)
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
mqttClient.publish(addrstr, valstr,true); mqttClient.publish(addrstr, valstr,true);
@@ -1831,6 +1963,7 @@ int Item::SendStatus(int sendFlags) {
setFlag(sendFlags); setFlag(sendFlags);
return 0; return 0;
} }
#endif
} }
@@ -1872,9 +2005,11 @@ int Item::SendStatus(int sendFlags) {
strncat(addrstr, subItem, sizeof(addrstr)-1); strncat(addrstr, subItem, sizeof(addrstr)-1);
} }
strncat(addrstr, "/", sizeof(addrstr)-1); strncat(addrstr, "/", sizeof(addrstr)-1);
strncat_P(addrstr, CMD_P, sizeof(addrstr)-1); // strncat_P(addrstr, CMD_P, sizeof(addrstr)-1);
strncat_P(addrstr, suffix_P[S_CMD], sizeof(addrstr)-1);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl; debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
#if not defined (NOIP)
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
mqttClient.publish(addrstr, cmdstr,true); mqttClient.publish(addrstr, cmdstr,true);
@@ -1885,6 +2020,7 @@ int Item::SendStatus(int sendFlags) {
setFlag(sendFlags); setFlag(sendFlags);
return 0; return 0;
} }
#endif
} }
// Send ctrl // Send ctrl
if (sendFlags & FLAG_FLAGS) if (sendFlags & FLAG_FLAGS)
@@ -1909,9 +2045,11 @@ int Item::SendStatus(int sendFlags) {
strncat(addrstr, subItem, sizeof(addrstr)-1); strncat(addrstr, subItem, sizeof(addrstr)-1);
} }
strncat(addrstr, "/", sizeof(addrstr)-1); strncat(addrstr, "/", sizeof(addrstr)-1);
strncat_P(addrstr, CTRL_P, sizeof(addrstr)-1); //strncat_P(addrstr, CTRL_P, sizeof(addrstr)-1);
strncat_P(addrstr, suffix_P[S_CTRL], sizeof(addrstr)-1);
debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl; debugSerial<<F("Pub: ")<<addrstr<<F("->")<<cmdstr<<endl;
#if not defined (NOIP)
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
mqttClient.publish(addrstr, cmdstr,true); mqttClient.publish(addrstr, cmdstr,true);
@@ -1922,6 +2060,7 @@ int Item::SendStatus(int sendFlags) {
setFlag(sendFlags); setFlag(sendFlags);
return 0; return 0;
} }
#endif //NOIP
} }
return 1; return 1;
} }
@@ -2006,38 +2145,6 @@ int Item::checkRetry() {
return M_CLEAN; return M_CLEAN;
} }
/*
bool Item::resumeModbus()
{
if (modbusBusy) return false;
bool success = true;
//debugSerial<<F("Pushing MB: ");
configLocked++;
if (items) {
aJsonObject * item = items->child;
while (items && item)
if (item->type == aJson_Array && aJson.getArraySize(item)>1) {
Item it(item);
if (it.isValid()) {
short res = it.checkModbusRetry();
if (res<=0) success = false;
} //isValid
yield();
item = item->next;
} //if
debugSerial<<endl;
}
configLocked--;
if (success) isPendedModbusWrites=false;
return true;
}
*/
//////////////////// Begin of legacy MODBUS code - to be moved in separate module ///////////////////// //////////////////// Begin of legacy MODBUS code - to be moved in separate module /////////////////////
@@ -2409,14 +2516,6 @@ int Item::checkModbusDimmer() {
uint16_t reg = getArg(MODBUS_CMD_ARG_REG); uint16_t reg = getArg(MODBUS_CMD_ARG_REG);
int _regType = MODBUS_HOLDING_REG_TYPE; int _regType = MODBUS_HOLDING_REG_TYPE;
if (numpar >= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint; if (numpar >= (MODBUS_CMD_ARG_REG_TYPE+1)) _regType = aJson.getArrayItem(itemArg, MODBUS_CMD_ARG_REG_TYPE)->valueint;
// short mask = getArg(2);
// debugSerial<<F("Modbus polling "));
// debugSerial<<addr);
// debugSerial<<F("=>"));
// debugSerial<<reg, HEX);
// debugSerial<<F("(T:"));
// debugSerial<<_regType);
// debugSerial<<F(")"));
int data; int data;
@@ -2454,7 +2553,7 @@ int Item::checkModbusDimmer() {
nextItem.checkModbusDimmer(data); nextItem.checkModbusDimmer(data);
pollingItem = pollingItem->next; pollingItem = pollingItem->next;
if (!pollingItem) if (!pollingItem)
pollingItem = items->child; pollingItem = rootItems->child;
} }
} else } else
debugSerial << F("MB: polling ") << itemArr->name<< F(" error=") << _HEX(result) << endl; debugSerial << F("MB: polling ") << itemArr->name<< F(" error=") << _HEX(result) << endl;

View File

@@ -37,6 +37,11 @@ e-mail anklimov@gmail.com
#define S_TEMP 12 #define S_TEMP 12
#define S_RAW 13 #define S_RAW 13
typedef char suffixstr[5];
const suffixstr suffix_P[] PROGMEM =
{"","cmd","set","val","del","HSV","RGB","fan","mode","ctrl","hue","sat","temp","raw"};
#define suffixNum sizeof(suffix_P)/sizeof(suffixstr)
#define S_ADDITIONAL 13 #define S_ADDITIONAL 13
#define CH_DIMMER 0 //DMX 1-4 ch #define CH_DIMMER 0 //DMX 1-4 ch
@@ -63,16 +68,6 @@ e-mail anklimov@gmail.com
#define CH_HUMIDIFIER 21 #define CH_HUMIDIFIER 21
#define CH_MERCURY 22 #define CH_MERCURY 22
//#define CHANNEL_TYPES 13
//static uint32_t pollInterval[CHANNEL_TYPES] = {0,0,0,0,MODB};
//static uint32_t nextPollTime[CHANNEL_TYPES] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
#define CH_WHITE 127//
#define POLLING_SLOW 1 #define POLLING_SLOW 1
#define POLLING_FAST 2 #define POLLING_FAST 2
#define POLLING_INT 3 #define POLLING_INT 3
@@ -103,16 +98,18 @@ extern aJsonObject *items;
extern short thermoSetCurTemp(char *name, float t); extern short thermoSetCurTemp(char *name, float t);
int txt2cmd (char * payload); int txt2cmd (char * payload);
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false); int txt2subItem(char *payload);
class Item class Item
{ {
public: public:
aJsonObject *itemArr, *itemArg,*itemVal,*itemExt; aJsonObject *rootItems, *itemArr, *itemArg,*itemVal,*itemExt;
uint8_t itemType; uint8_t itemType;
abstractOut * driver; abstractOut * driver;
Item(char * name); Item(char * name, aJsonObject *_items = items);
Item(aJsonObject * obj); Item(aJsonObject * obj, aJsonObject *_items = items);
Item(uint16_t num, uint8_t subItem, aJsonObject *_items = items);
~Item(); ~Item();
boolean isValid (); boolean isValid ();
@@ -151,30 +148,25 @@ class Item
int scheduleCommand(itemCmd cmd, bool authorized); int scheduleCommand(itemCmd cmd, bool authorized);
int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized); int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized);
int isScheduled(); int isScheduled();
char * getSubItemStrById(uint8_t subItem);
uint8_t getSubitemId(char * subItem);
protected: protected:
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false);
long int limitSetValue(); long int limitSetValue();
int VacomSetFan (itemCmd st); int VacomSetFan (itemCmd st);
int VacomSetHeat(itemCmd st); int VacomSetHeat(itemCmd st);
int modbusDimmerSet(itemCmd st); int modbusDimmerSet(itemCmd st);
int modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint16_t value); int modbusDimmerSet(int addr, uint16_t _reg, int _regType, int _mask, uint16_t value);
void mb_fail(int result=0); void mb_fail(int result=0);
void Parse(); void Parse();
int checkModbusDimmer(); int checkModbusDimmer();
int checkModbusDimmer(int data); int checkModbusDimmer(int data);
int checkRetry(); int checkRetry();
//boolean checkVCRetry();
//boolean checkHeatRetry();
void sendDelayedStatus(); void sendDelayedStatus();
//bool resumeModbus();
int checkFM(); int checkFM();
char defaultSubItem[16]; char defaultSubItem[16];
int defaultSuffixCode; int defaultSuffixCode;
}; };
typedef union typedef union

View File

@@ -94,6 +94,86 @@ itemCmd::itemCmd(Item *item)
loadItem(item); loadItem(item);
} }
/*!
\brief Constructor with textual definition of command
\param cmd - name of cmd
todo - extend to values
*/
itemCmd::itemCmd(char * _cmd)
{
//debugSerial<<"ITEMCMD:" <<_cmd<<endl;
cmd.aslong=0;
param.aslong=0;
short i=0;
int Par[4];
while (_cmd[i]) {_cmd[i]=toupper(_cmd[i]);i++;};
int cmdN = txt2cmd(_cmd);
if (cmdN>=0) cmd.cmdCode = cmdN;
bool hsvflag=false;
switch (cmd.cmdCode) {
case CMD_HSV:
hsvflag=true;
case CMD_RGB:
cmd.cmdCode=CMD_VOID;
//Parsing integers from payload
i = 0;
while (_cmd && i < 4)
Par[i++] = getIntFromStr((char **) &_cmd);
if (hsvflag)
{
setSuffix(S_HSV);
cmd.itemArgType=ST_HSV255;
switch (i) //Number of params
{
case 4:
setColorTemp(Par[3]);
case 3:
param.v=Par[2];
case 2:
setH(Par[0]);
setS(Par[1]);
}
}
else
{
setSuffix(S_RGB);
switch (i) //Number of params
{
case 3: RGB(Par[0],Par[1],Par[2]);
break;
case 4: RGBW(Par[0],Par[1],Par[2],Par[3]);
default:;
}
}
break;
// case CMD_UNKNOWN: //Not known command
// case CMD_JSON: //JSON input (not implemented yet
// cmd.cmdCode=CMD_VOID;
// break;
default: //some known command
//case CMD_VOID:
//case CMD_UP:
//case CMD_DN:
{
itemCmd num =getNumber((char **) &_cmd);
cmd.itemArgType=num.getArgType();
param.aslong=num.param.aslong;
if (cmd.cmdCode) setSuffix(S_CMD);
}
} //switch
//debugOut();
}
itemCmd itemCmd::setChanType(short chanType) itemCmd itemCmd::setChanType(short chanType)
{ {
@@ -596,7 +676,7 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
{ {
long coldPercent = map (colorT,0,100,100,30); long coldPercent = map (colorT,0,100,100,30);
long hotPercent = map (colorT,0,100,30,100); long hotPercent = map (colorT,0,100,30,100);
int rgbvLevel; int rgbvLevel = 0;
if (rgbSaturation < 128) { // Using white if (rgbSaturation < 128) { // Using white
param.w=map((127 - rgbSaturation) * rgbValue *hotPercent, 0, 127*255*100, 0, 255); param.w=map((127 - rgbSaturation) * rgbValue *hotPercent, 0, 127*255*100, 0, 255);
@@ -1151,6 +1231,7 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
break; break;
default: default:
item->setCmd(cmd.cmdCode); item->setCmd(cmd.cmdCode);
} }
if (optionsFlag & FLAG_PARAMETERS) if (optionsFlag & FLAG_PARAMETERS)
switch (cmd.itemArgType) switch (cmd.itemArgType)
@@ -1171,8 +1252,8 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
item->setVal(param.asInt32); item->setVal(param.asInt32);
item->setSubtype(cmd.itemArgType); item->setSubtype(cmd.itemArgType);
} }
debugSerial<<F("Saved:"); //debugSerial<<F("Saved:");
debugOut(); //debugOut();
return true; return true;
} }
return false; return false;
@@ -1196,7 +1277,13 @@ return false;
int replaceTypeToInt(aJsonObject* verb) int replaceTypeToInt(aJsonObject* verb)
{ {
if (verb && verb->type == aJson_String) if (!verb) return -1;
switch (verb->type)
{
case aJson_Int: return verb->valueint;
case aJson_Array: return replaceTypeToInt(verb->child);
case aJson_Object: return replaceTypeToInt(aJson.getObjectItem(verb, "type"));
case aJson_String:
{ {
int type = type2num(verb->valuestring); int type = type2num(verb->valuestring);
if (type>=0) if (type>=0)
@@ -1206,7 +1293,9 @@ return false;
verb->type=aJson_Int; verb->type=aJson_Int;
return verb->valueint; return verb->valueint;
} }
} else if (verb && verb->type == aJson_Int) return verb->valueint; }
break;
}
return -1; return -1;
} }
@@ -1222,7 +1311,7 @@ return false;
{ {
case aJson_Array: case aJson_Array:
{ {
debugSerial<<"Array mapping"<<endl; traceSerial<<"Array mapping"<<endl;
aJsonObject *i = cmdMapping->child; aJsonObject *i = cmdMapping->child;
//if first array element is not array - this is default mapping value //if first array element is not array - this is default mapping value
if (i && i->type==aJson_Int) if (i && i->type==aJson_Int)

View File

@@ -119,7 +119,7 @@ const ch_type ch_type_P[] PROGMEM =
#define FLAG_HALTED 0x40000UL #define FLAG_HALTED 0x40000UL
#define FLAG_XON 0x80000UL #define FLAG_XON 0x80000UL
#define FLAG_NOT_SEND_CAN 0x2UL
int txt2cmd (char * payload); int txt2cmd (char * payload);
@@ -157,10 +157,9 @@ typedef union
struct struct
{ {
uint8_t cmdCode; uint8_t cmdCode;
uint8_t suffixCode:4;
uint8_t itemArgType:4; uint8_t itemArgType:4;
uint8_t cmdEffect:4; //Reserve
uint8_t cmdEffect; //Reserve uint8_t suffixCode;
uint8_t cmdParam; //Reserve uint8_t cmdParam; //Reserve
}; };
} itemCmdStore; } itemCmdStore;
@@ -204,6 +203,7 @@ public:
itemCmd(uint8_t _type=ST_VOID, uint8_t _code=CMD_VOID); itemCmd(uint8_t _type=ST_VOID, uint8_t _code=CMD_VOID);
itemCmd(float val); itemCmd(float val);
itemCmd(Item *item); itemCmd(Item *item);
itemCmd(char *cmd);
itemCmd assignFrom(itemCmd from, short chanType=-1); itemCmd assignFrom(itemCmd from, short chanType=-1);

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,17 @@
#if defined(__SAM3X8E__) #if defined(__SAM3X8E__)
#include <watchdog.h> #include <watchdog.h>
#if not defined (NOIP)
#include <ArduinoHttpClient.h> #include <ArduinoHttpClient.h>
#endif
//#include "TimerInterrupt_Generic.h" //#include "TimerInterrupt_Generic.h"
#endif #endif
#if defined(ARDUINO_ARCH_AVR) #if defined(ARDUINO_ARCH_AVR)
#if not defined (NOIP)
#include "HTTPClient.h" #include "HTTPClient.h"
//#include <ArduinoHttpClient.h> #endif
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include <avr/wdt.h> #include <avr/wdt.h>
#endif #endif
@@ -35,7 +39,7 @@
//#define Ethernet WiFi //#define Ethernet WiFi
#endif #endif
#if defined ARDUINO_ARCH_ESP32 #if defined (ARDUINO_ARCH_ESP32)
#include <FS.h> //this needs to be first, or it all crashes and burns... #include <FS.h> //this needs to be first, or it all crashes and burns...
//#include "SPIFFS.h" //#include "SPIFFS.h"
//#include <EEPROM.h> //#include <EEPROM.h>
@@ -58,7 +62,7 @@
#include <ArduinoHttpClient.h> #include <ArduinoHttpClient.h>
#endif #endif
#ifdef ARDUINO_ARCH_STM32 #if defined (ARDUINO_ARCH_STM32) and not defined (NOIP)
#include "HttpClient.h" #include "HttpClient.h"
//#include "UIPEthernet.h" //#include "UIPEthernet.h"
//#include <NRFFlashStorage.h> //#include <NRFFlashStorage.h>
@@ -156,7 +160,8 @@ extern Streamlog errorSerial;
#include <ESP8266mDNS.h> #include <ESP8266mDNS.h>
#endif #endif
#define Ethernet WiFi #define Ethernet WiFi
#else //Wired connection #else
#if not defined (NOIP) //Wired connection
#ifdef Wiz5500 #ifdef Wiz5500
#include <Ethernet2.h> #include <Ethernet2.h>
#else #else
@@ -167,6 +172,7 @@ extern Streamlog errorSerial;
#endif #endif
#endif #endif
#endif #endif
#endif
#ifdef _artnet #ifdef _artnet
@@ -190,7 +196,9 @@ extern Streamlog errorSerial;
#include "Arduino.h" #include "Arduino.h"
#include "utils.h" #include "utils.h"
#include "textconst.h" #include "textconst.h"
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
#endif
#include <SPI.h> #include <SPI.h>
#include <string.h> #include <string.h>
#include "aJSON.h" #include "aJSON.h"
@@ -198,6 +206,9 @@ extern Streamlog errorSerial;
#include "stdarg.h" #include "stdarg.h"
#include "item.h" #include "item.h"
#include "inputs.h" #include "inputs.h"
#ifdef CANDRV
#include <candriver.h>
#endif
#ifdef _artnet #ifdef _artnet
extern Artnet *artnet; extern Artnet *artnet;
@@ -218,7 +229,11 @@ enum lan_status {
RECONNECT = 13, RECONNECT = 13,
READ_RE_CONFIG = 14, READ_RE_CONFIG = 14,
DO_READ_RE_CONFIG = 15, DO_READ_RE_CONFIG = 15,
DO_NOTHING = -15 DO_NOTHING = -15,
DO_GET = -16,
GET = -17,
GET_IN_PROGRESS = 18,
AWAITING_CONFIG = 19
}; };
extern lan_status lanStatus; extern lan_status lanStatus;
@@ -230,11 +245,18 @@ typedef union {
bool isNotRetainingStatus(); bool isNotRetainingStatus();
#if not defined (NOIP)
void mqttCallback(char *topic, byte *payload, unsigned int length); void mqttCallback(char *topic, byte *payload, unsigned int length);
void printMACAddress();
lan_status lanLoop(); lan_status lanLoop();
int loadConfigFromHttp();
void onInitialStateInitLAN();
void onMQTTConnect();
void ip_ready_config_loaded_connecting_to_broker();
#endif
void setupMacAddress();
void printMACAddress();
#ifndef OWIRE_DISABLE #ifndef OWIRE_DISABLE
void Changed(int i, DeviceAddress addr, float currentTemp); void Changed(int i, DeviceAddress addr, float currentTemp);
@@ -271,7 +293,7 @@ void saveFlash(short n, IPAddress& ip);
int ipLoadFromFlash(short n, IPAddress &ip); int ipLoadFromFlash(short n, IPAddress &ip);
*/ */
int loadConfigFromHttp();
void preTransmission(); void preTransmission();
@@ -303,8 +325,6 @@ void printConfigSummary();
void setupCmdArduino(); void setupCmdArduino();
void setupMacAddress();
void printFirmwareVersionAndBuildOptions(); void printFirmwareVersionAndBuildOptions();
bool IsThermostat(const aJsonObject *item); bool IsThermostat(const aJsonObject *item);
@@ -313,14 +333,13 @@ bool disabledDisconnected(const aJsonObject *thermoExtensionArray, int thermoLat
void resetHard(); void resetHard();
void onInitialStateInitLAN(); bool cleanConf(bool wait);
void ip_ready_config_loaded_connecting_to_broker();
void printCurentLanConfig(); void printCurentLanConfig();
void onMQTTConnect();
int16_t attachMaturaTimer(); int16_t attachMaturaTimer();
void setFirstBroker();
void setNextBroker();
//void printFreeRam(); //void printFreeRam();

View File

@@ -22,14 +22,14 @@ static bool CCS811ready = false;
int in_ccs811::Setup() int in_ccs811::Setup()
{ {
if (CCS811ready) {errorSerial<<F("ccs811 is already initialized")<<endl; return 0;} if (CCS811ready) {errorSerial<<F("CCS811: Already initialized")<<endl; return 0;}
#ifdef WAK_PIN #ifdef WAK_PIN
pinMode(WAK_PIN,OUTPUT); pinMode(WAK_PIN,OUTPUT);
digitalWrite(WAK_PIN,LOW); digitalWrite(WAK_PIN,LOW);
#endif #endif
infoSerial.println("CCS811 Init"); infoSerial.println(F("CCS811: Init"));
#if defined (TWI_SCL) && defined (TWI_SDA) #if defined (TWI_SCL) && defined (TWI_SDA)
Wire.begin(TWI_SDA,TWI_SCL); //Inialize I2C Harware Wire.begin(TWI_SDA,TWI_SCL); //Inialize I2C Harware
@@ -37,7 +37,9 @@ Wire.begin(TWI_SDA,TWI_SCL); //Inialize I2C Harware
Wire.begin(); //Inialize I2C Harware Wire.begin(); //Inialize I2C Harware
#endif #endif
Wire.setClock(4000); #ifdef I2C_CLOCK
Wire.setClock(I2C_CLOCK);
#endif
//It is recommended to check return status on .begin(), but it is not //It is recommended to check return status on .begin(), but it is not
//required. //required.
@@ -46,8 +48,7 @@ Wire.setClock(4000);
if (returnCode != CCS811Core::SENSOR_SUCCESS) if (returnCode != CCS811Core::SENSOR_SUCCESS)
//if (returnCode != CCS811Core::CCS811_Stat_SUCCESS) //if (returnCode != CCS811Core::CCS811_Stat_SUCCESS)
{ {
errorSerial.print("CCS811 Init error "); errorSerial.print(F("CCS811: Init error "));
//debugSerial.println(ccs811.statusString(returnCode));
printDriverError(returnCode); printDriverError(returnCode);
return 0; return 0;
} }
@@ -68,16 +69,16 @@ return 1;
int in_hdc1080::Setup() int in_hdc1080::Setup()
{ {
//i2cReset(); //i2cReset();
if (HDC1080ready) {debugSerial<<F("hdc1080 is already initialized")<<endl; return 0;} if (HDC1080ready) {debugSerial<<F("HDC1080: Already initialized")<<endl; return 0;}
debugSerial.println("HDC1080 Init "); debugSerial.print(F("HDC1080: Init. "));
Wire.begin(); //Inialize I2C Harware Wire.begin(); //Inialize I2C Harware
// Default settings: // Default settings:
// - Heater off // - Heater off
// - 14 bit Temperature and Humidity Measurement Resolutions // - 14 bit Temperature and Humidity Measurement Resolutions
hdc1080.begin(0x40); hdc1080.begin(0x40);
debugSerial.print("Manufacturer ID=0x"); debugSerial.print(F("Manufacturer ID=0x"));
debugSerial.println(hdc1080.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments debugSerial.print(hdc1080.readManufacturerId(), HEX); // 0x5449 ID of Texas Instruments
debugSerial.print("Device ID=0x"); debugSerial.print(F(" Device ID=0x"));
debugSerial.println(hdc1080.readDeviceId(), HEX); // 0x1050 ID of the device debugSerial.println(hdc1080.readDeviceId(), HEX); // 0x1050 ID of the device
printSerialNumber(); printSerialNumber();
HDC1080ready = true; HDC1080ready = true;
@@ -91,14 +92,14 @@ int in_hdc1080::Poll(short cause)
float h,t; float h,t;
int reg; int reg;
if (cause!=POLLING_SLOW) return 0; if (cause!=POLLING_SLOW) return 0;
if (!HDC1080ready) {debugSerial<<F("HDC1080 not initialized")<<endl; return 0;} if (!HDC1080ready) {errorSerial<<F("HDC1080: Not initialized")<<endl; return 0;}
debugSerial.print("HDC Status="); debugSerial.print(F("HDC1080: Status="));
debugSerial.println(reg=hdc1080.readRegister().rawData,HEX); debugSerial.print(reg=hdc1080.readRegister().rawData,HEX);
if (reg!=0xff) if (reg!=0xff)
{ {
debugSerial.print(" T="); debugSerial.print(" T=");
debugSerial.print(t=hdc1080.readTemperature()); debugSerial.print(t=hdc1080.readTemperature());
debugSerial.print("C, RH="); debugSerial.print(F("C, RH="));
debugSerial.print(h=hdc1080.readHumidity()); debugSerial.print(h=hdc1080.readHumidity());
debugSerial.println("%"); debugSerial.println("%");
@@ -126,6 +127,7 @@ if (reg!=0xff)
} }
else //ESP I2C glitch else //ESP I2C glitch
{ {
debugSerial.println();
i2cReset(); i2cReset();
} }
return INTERVAL_SLOW_POLLING; return INTERVAL_SLOW_POLLING;
@@ -147,14 +149,14 @@ int in_ccs811::Poll(short cause)
CCS811Core::status returnCode = ccs811.readAlgorithmResults(); CCS811Core::status returnCode = ccs811.readAlgorithmResults();
printDriverError(returnCode); printDriverError(returnCode);
float co2,tvoc; float co2,tvoc;
debugSerial.print(" CO2["); debugSerial.print(F(" CO2["));
//Returns calculated CO2 reading //Returns calculated CO2 reading
debugSerial.print(co2 = ccs811.getCO2()); debugSerial.print(co2 = ccs811.getCO2());
debugSerial.print("] tVOC["); debugSerial.print(F("] tVOC["));
//Returns calculated TVOC reading //Returns calculated TVOC reading
debugSerial.print(tvoc = ccs811.getTVOC()); debugSerial.print(tvoc = ccs811.getTVOC());
debugSerial.print("] baseline["); debugSerial.print(F("] baseline["));
debugSerial.print(ccs811Baseline = ccs811.getBaseline()); debugSerial.print(ccs811Baseline = ccs811.getBaseline());
#ifdef M5STACK #ifdef M5STACK
@@ -192,11 +194,11 @@ int in_ccs811::Poll(short cause)
} }
void in_hdc1080::printSerialNumber() { void in_hdc1080::printSerialNumber() {
debugSerial.print("Device Serial Number="); infoSerial.print(F("Device Serial Number="));
HDC1080_SerialNumber sernum = hdc1080.readSerialNumber(); HDC1080_SerialNumber sernum = hdc1080.readSerialNumber();
char format[16]; char format[16];
sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast); sprintf(format, "%02X-%04X-%04X", sernum.serialFirst, sernum.serialMid, sernum.serialLast);
debugSerial.println(format); infoSerial.println(format);
} }
//printDriverError decodes the CCS811Core::status type and prints the //printDriverError decodes the CCS811Core::status type and prints the
@@ -206,25 +208,26 @@ debugSerial.println(format);
//to this function to see what the output was. //to this function to see what the output was.
void in_ccs811::printDriverError( CCS811Core::status errorCode ) void in_ccs811::printDriverError( CCS811Core::status errorCode )
{ {
debugSerial.print(F("CCS811: "));
switch ( errorCode ) switch ( errorCode )
{ {
case CCS811Core::SENSOR_SUCCESS: case CCS811Core::SENSOR_SUCCESS:
debugSerial.print("SUCCESS"); debugSerial.print(F("SUCCESS"));
break; break;
case CCS811Core::SENSOR_ID_ERROR: case CCS811Core::SENSOR_ID_ERROR:
debugSerial.print("ID_ERROR"); debugSerial.print(F("ID_ERROR"));
break; break;
case CCS811Core::SENSOR_I2C_ERROR: case CCS811Core::SENSOR_I2C_ERROR:
debugSerial.print("I2C_ERROR"); debugSerial.print(F("I2C_ERROR"));
break; break;
case CCS811Core::SENSOR_INTERNAL_ERROR: case CCS811Core::SENSOR_INTERNAL_ERROR:
debugSerial.print("INTERNAL_ERROR"); debugSerial.print(F("INTERNAL_ERROR"));
break; break;
case CCS811Core::SENSOR_GENERIC_ERROR: case CCS811Core::SENSOR_GENERIC_ERROR:
debugSerial.print("GENERIC_ERROR"); debugSerial.print(F("GENERIC_ERROR"));
break; break;
default: default:
debugSerial.print("Unspecified error."); debugSerial.print(F("Unspecified error."));
} }
} }
@@ -236,18 +239,18 @@ void in_ccs811::printSensorError()
if ( error == 0xFF ) //comm error if ( error == 0xFF ) //comm error
{ {
debugSerial.println("Failed to get ERROR_ID register."); errorSerial.println(F("CCS811: Failed to get ERROR_ID register."));
} }
else else
{ {
//debugSerial.print(""); if (error) errorSerial.print(F("CCS811: Error "));
if (error & 1 << 5) debugSerial.print("Error: HeaterSupply"); if (error & 1 << 5) errorSerial.print(F("HeaterSupply"));
if (error & 1 << 4) debugSerial.print("Error: HeaterFault"); if (error & 1 << 4) errorSerial.print(F("HeaterFault"));
if (error & 1 << 3) debugSerial.print("Error: MaxResistance"); if (error & 1 << 3) errorSerial.print(F("MaxResistance"));
if (error & 1 << 2) debugSerial.print("Error: MeasModeInvalid"); if (error & 1 << 2) errorSerial.print(F("MeasModeInvalid"));
if (error & 1 << 1) debugSerial.print("Error: ReadRegInvalid"); if (error & 1 << 1) errorSerial.print(F("ReadRegInvalid"));
if (error & 1 << 0) debugSerial.print("Error: MsgInvalid"); if (error & 1 << 0) errorSerial.print(F("MsgInvalid"));
debugSerial.println(); if (error) errorSerial.println();
} }
} }
#endif #endif

View File

@@ -7,18 +7,22 @@
#include "ClosedCube_HDC1080.h" #include "ClosedCube_HDC1080.h"
#include "SparkFunCCS811.h" //Click here to get the library: http://librarymanager/All#SparkFun_CCS811 #include "SparkFunCCS811.h" //Click here to get the library: http://librarymanager/All#SparkFun_CCS811
//#ifndef I2C_CLOCK
//#define I2C_CLOCK 4000
//#endif
//#define CCS811_ADDR 0x5B //Default I2C Address //#define CCS811_ADDR 0x5B //Default I2C Address
#define CCS811_ADDR 0x5A //Alternate I2C Address #define CCS811_ADDR 0x5A //Alternate I2C Address
#if defined (ARDUINO_ARCH_ESP8266) #if defined (ARDUINO_ARCH_ESP8266)
#if not defined (TWI_SCL) && defined (D1) // #if not defined (TWI_SCL) && defined (D1)
#define TWI_SCL D1 // #define TWI_SCL D1
#endif // #endif
#if not defined (WAK_PIN) && defined (D3) // #if not defined (WAK_PIN) && defined (D3)
#define WAK_PIN D3 // #define WAK_PIN D3
#endif // #endif
#if defined (TWI_SCL) #if defined (TWI_SCL)
#define SCL_LOW() (GPES = (1 << TWI_SCL)) #define SCL_LOW() (GPES = (1 << TWI_SCL))
@@ -28,16 +32,10 @@
#endif #endif
/*
#if defined (__SAM3X8E__)
#define SCL_LOW() digitalWrite(21,LOW)
#define SCL_HIGH() digitalWrite(21,HIGH)
#define SCL_RESET
#endif
*/
#if defined (ARDUINO_ARCH_ESP32) #if defined (ARDUINO_ARCH_ESP32)
#undef WAK_PIN //#undef WAK_PIN
#undef SCL_RESET #undef SCL_RESET
//#ifndef WAK_PIN //#ifndef WAK_PIN
//#define WAK_PIN 17 //#define WAK_PIN 17
@@ -45,9 +43,9 @@
#endif #endif
#if defined(ARDUINO_ARCH_AVR) #if defined(ARDUINO_ARCH_AVR)
#ifndef WAK_PIN //#ifndef WAK_PIN
#define WAK_PIN 3 // for LightHub UEXT SCS Pin //#define WAK_PIN 3 // for LightHub UEXT SCS Pin
#endif //#endif
#endif #endif

View File

@@ -22,7 +22,9 @@ extern bool disableCMD;
#define AC_FAILED CST_FAILED #define AC_FAILED CST_FAILED
#define AC_UNKNOWN CST_UNKNOWN #define AC_UNKNOWN CST_UNKNOWN
#define AC_IDLE CST_INITIALIZED #define AC_IDLE CST_INITIALIZED
#define AC_SENDING 3 #define AC_SENDING CST_USER
#define AC_AWAITINGCMD CST_USER+1
#define AC_POLL CST_USER+2
//byte inCheck = 0; //byte inCheck = 0;
byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса
@@ -237,6 +239,7 @@ SubmitParameters("fan",icmd);
if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);} if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);}
publishTopic(item->itemArr->name, s_buffer,"/cmd"); publishTopic(item->itemArr->name, s_buffer,"/cmd");
SubmitParameters("cmd",icmd); SubmitParameters("cmd",icmd);
/* /*
if (store->power & 0x01) if (store->power & 0x01)
publishTopic(item->itemArr->name, s_buffer,"/cmd"); publishTopic(item->itemArr->name, s_buffer,"/cmd");
@@ -393,16 +396,46 @@ case AC_SENDING:
store->timestamp=millisNZ(); store->timestamp=millisNZ();
} }
} }
break;
case AC_AWAITINGCMD: //Flusing port for 5 sec, poll status
if (store->timestamp && isTimeOver(store->timestamp,millis(),5000))
{
setStatus(AC_POLL);
store->timestamp=millisNZ();
store->inCheck=0;
debugSerial<<F("AC: Unmute")<<endl;
}
while(ACSerial->available())
{
delay(2);
ACSerial->read();
}
return true;
case AC_IDLE:
if (store->timestamp && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING)) setStatus(AC_POLL);
if (cause!=POLLING_SLOW) return false;
break;
case AC_POLL:
if (cause!=POLLING_SLOW) return false;
debugSerial.println(F("AC: Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
store->timestamp=millisNZ();
setStatus(AC_IDLE);
} }
if (cause!=POLLING_SLOW) return false; /*if (cause!=POLLING_SLOW) return false;
if ((Status() == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING)) if ((Status() == AC_IDLE) && isTimeOver(store->timestamp,millis(),INTERVAL_AC_POLLING))
{ {
debugSerial.println(F("AC: Polling")); debugSerial.println(F("AC: Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
} }
*/
if(ACSerial->available() >= 37){ //was 0 if(ACSerial->available() >= 37){ //was 0
ACSerial->readBytes(store->data, 37); ACSerial->readBytes(store->data, 37);
while(ACSerial->available()){ while(ACSerial->available()){
@@ -468,6 +501,10 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
case S_CMD: case S_CMD:
// s_mode[0]='\0'; // s_mode[0]='\0';
store->timestamp=millisNZ();
setStatus(AC_AWAITINGCMD);
switch (cmd.getCmd()) switch (cmd.getCmd())
{ {
case CMD_ON: case CMD_ON:
@@ -475,7 +512,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_POWER] = store->power; store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1; store->data[B_POWER] |= 1;
SendData(on, sizeof(on)/sizeof(byte)); SendData(on, sizeof(on)/sizeof(byte));
// publishTopic(item->itemArr->name,"ON","/cmd"); //publishTopic(item->itemArr->name,"ON","/cmd"); //
return 1; return 1;
break; break;
case CMD_OFF: case CMD_OFF:
@@ -483,7 +520,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_POWER] = store->power; store->data[B_POWER] = store->power;
store->data[B_POWER] &= ~1; store->data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte)); SendData(off, sizeof(off)/sizeof(byte));
// publishTopic(item->itemArr->name,"OFF","/cmd"); publishTopic(item->itemArr->name,"OFF","/cmd"); //
return 1; return 1;
break; break;
case CMD_AUTO: case CMD_AUTO:
@@ -549,9 +586,43 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_FAN_SPD] = 2; store->data[B_FAN_SPD] = 2;
strcpy_P(s_speed,LOW_P); strcpy_P(s_speed,LOW_P);
break; break;
case CMD_OFF:
store->inCheck=0;
store->timestamp=millisNZ();
store->data[B_POWER] = store->power;
store->data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte));
return 1;
default: default:
//if (n) data[B_FAN_SPD] = Parameters[0]; {
store->data[B_FAN_SPD] = cmd.getInt(); uint8_t speed = 0;
if (cmd.getInt()) speed = map(cmd.getInt(),1,255,1,3);
store->inCheck=0;
switch (speed) {
case 0:
store->data[B_POWER] = store->power;
store->data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte));
return 1;
case 1:
store->data[B_FAN_SPD] = 2;
strcpy_P(s_speed,LOW_P);
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
break;
case 2:
store->data[B_FAN_SPD] = 1;
strcpy_P(s_speed,MED_P);
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
break;
case 3:
store->data[B_FAN_SPD] = 0;
strcpy_P(s_speed,HIGH_P);
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
}
}
//TODO - mapping digits to speed //TODO - mapping digits to speed
} }
publishTopic(item->itemArr->name,s_speed,"/fan"); publishTopic(item->itemArr->name,s_speed,"/fan");

View File

@@ -42,7 +42,7 @@ public:
int Stop() override; int Stop() override;
int isActive() override; int isActive() override;
int getChanType() override; int getChanType() override;
int getDefaultStorageType(){return ST_FLOAT_CELSIUS;}; // int getDefaultStorageType(){return ST_FLOAT_CELSIUS;};
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
void SubmitParameters(const char * name, itemCmd value); void SubmitParameters(const char * name, itemCmd value);

View File

@@ -97,6 +97,7 @@ debugSerial.println("Mercury: De-Init");
disconnectMercury(); disconnectMercury();
delete store; delete store;
item->setPersistent(NULL); item->setPersistent(NULL);
setStatus(CST_UNKNOWN);
store = NULL; store = NULL;
return 1; return 1;
} }

View File

@@ -20,16 +20,16 @@ public:
#define MB_SEND_ERROR 4 #define MB_SEND_ERROR 4
#define MB_SEND_ATTEMPTS 3 #define MB_SEND_ATTEMPTS 3
#define M_CONNECTING 10 #define M_CONNECTING CST_USER+0
#define M_CONNECTED 11 #define M_CONNECTED CST_USER+1
#define M_POLLING1 12 #define M_POLLING1 CST_USER+2
#define M_POLLING2 13 #define M_POLLING2 CST_USER+3
#define M_POLLING3 14 #define M_POLLING3 CST_USER+4
#define M_POLLING4 15 #define M_POLLING4 CST_USER+5
#define M_POLLING5 16 #define M_POLLING5 CST_USER+6
#define M_POLLING6 17 #define M_POLLING6 CST_USER+7
#define M_POLLING7 18 #define M_POLLING7 CST_USER+8
#define M_POLLING8 19 #define M_POLLING8 CST_USER+9
#define RET_SUCCESS 0 #define RET_SUCCESS 0
#define RET_INVALID_PARAM 1 #define RET_INVALID_PARAM 1
@@ -48,7 +48,7 @@ public:
int Stop() override; int Stop() override;
int getChanType() override; int getChanType() override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
int getDefaultStorageType(){return ST_INT32;}; //int getDefaultStorageType(){return ST_INT32;};
protected: protected:

View File

@@ -60,45 +60,6 @@ const reg_t regSize_P[] PROGMEM =
} ; } ;
#define regSizeNum sizeof(regSize_P)/sizeof(reg_t) #define regSizeNum sizeof(regSize_P)/sizeof(reg_t)
/*
const serial_t serialModes_P[] PROGMEM =
{
{ "8E1", (serialParamType) SERIAL_8E1},//(uint16_t) US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_EVEN },
{ "8N1", (serialParamType) SERIAL_8N1},
{ "8E2", (serialParamType) SERIAL_8E2},
{ "8N2", (serialParamType) SERIAL_8N2},
{ "8O1", (serialParamType) SERIAL_8O1},
{ "8O2", (serialParamType) SERIAL_8O2},
// { "8M1", SERIAL_8M1},
// { "8S1", SERIAL_8S1},
{ "7E1", (serialParamType) SERIAL_7E1},//(uint16_t) US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_EVEN },
{ "7N1", (serialParamType) SERIAL_7N1},
{ "7E2", (serialParamType) SERIAL_7E2},
{ "7N2", (serialParamType) SERIAL_7N2},
{ "7O1", (serialParamType) SERIAL_7O1},
{ "7O2", (serialParamType) SERIAL_7O2}
// { "7M1", SERIAL_7M1},
// { "7S1", SERIAL_7S1}
} ;
#define serialModesNum sizeof(serialModes_P)/sizeof(serial_t)
serialParamType str2SerialParam(char * str)
{ debugSerial<<str<<F(" =>");
for(uint8_t i=0; i<serialModesNum && str;i++)
if (strcmp_P(str, serialModes_P[i].verb) == 0)
{
//debugSerial<< i << F(" ") << pgm_read_word_near(&serialModes_P[i].mode)<< endl;
if (sizeof(serialModesNum)==4)
return pgm_read_dword_near(&serialModes_P[i].mode);
else
return pgm_read_word_near(&serialModes_P[i].mode);
}
debugSerial<< F("Default serial mode N81 used");
return static_cast<serialParamType> (SERIAL_8N1);
}
*/
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);} uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
int str2regSize(char * str) int str2regSize(char * str)
@@ -223,6 +184,7 @@ switch (regType) {
break; break;
default: default:
debugSerial<<F("MBUS: Not supported reg type\n"); debugSerial<<F("MBUS: Not supported reg type\n");
return false;
} }
mbusSlenceTimer = millisNZ(); mbusSlenceTimer = millisNZ();
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl; if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl;
@@ -327,7 +289,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
mappedParam.Int((uint32_t)param); mappedParam.Int((uint32_t)param);
} }
debugSerial << F("MBUSD: got ")<<mappedParam.toString(buf,sizeof(buf))<< F(" from type ")<<parType<<F(":")<<paramObj->name<<endl; traceSerial << F("MBUSD: got ")<<mappedParam.toString(buf,sizeof(buf))<< F(" from type ")<<parType<<F(":")<<paramObj->name<<endl;
if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object)) if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object))
{ {
@@ -341,30 +303,40 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
switch (defMappingObj->type) switch (defMappingObj->type)
{ {
case aJson_Int: //register/coil/.. number case aJson_Int: //register/coil/.. number
debugSerial<<F("Searching reg#")<<defMappingObj->valueint<<endl; traceSerial<<F("Searching reg#")<<defMappingObj->valueint<<endl;
if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo)) if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo))
{ {
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut); mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
executeWithoutCheck=true; executeWithoutCheck=true;
} }
else errorSerial<<F("reg# out of range")<<endl; else
{
debugSerial<<F("def reg# ")<<defMappingObj->valueint<<F(" out of range buffer, fetching")<<endl;
////to prevent CORRUPTION if using same buffer
uint16_t localBuffer;
node.setResponseBuffer(&localBuffer,1);
if (readModbus(defMappingObj->valueint,regType,1))
{
mappedParam = findRegister(defMappingObj->valueint,0,regType,defMappingObj->valueint,defMappingObj->valueint,false,&submitRecurrentOut);
executeWithoutCheck=true;
}
node.setDefaultResponseBuffer();
}
break; break;
case aJson_String: // parameter name case aJson_String: // parameter name
debugSerial<<F("Searching reg: ")<<defMappingObj->valuestring<<endl; traceSerial<<F("Searching reg: ")<<defMappingObj->valuestring<<endl;
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
//Searching item param for nested mapping //Searching item param for nested mapping
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring); aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
if (itemParObj) if (itemParObj)
{ {
//aJsonObject * markObj = execObj;
//if (execObj->type == aJson_Array) markObj = execObj->child;
//Retrive previous data //Retrive previous data
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S"); aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
if (lastMeasured && lastMeasured->type ==aJson_Int) if (lastMeasured && lastMeasured->type ==aJson_Int)
{ {
debugSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl; traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
//Searching template param for nested mapping //Searching template param for nested mapping
aJsonObject * templateParObj = aJson.getObjectItem(store->parameters,defMappingObj->valuestring); aJsonObject * templateParObj = aJson.getObjectItem(store->parameters,defMappingObj->valuestring);
if (templateParObj) if (templateParObj)
@@ -401,7 +373,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
aJsonObject * nestedMapObj = aJson.getObjectItem(templateParObj, "map"); aJsonObject * nestedMapObj = aJson.getObjectItem(templateParObj, "map");
if (nestedMapObj && (nestedMapObj->type==aJson_Array || nestedMapObj->type==aJson_Object)) mappedParam=mappedParam.doReverseMapping(nestedMapObj); if (nestedMapObj && (nestedMapObj->type==aJson_Array || nestedMapObj->type==aJson_Object)) mappedParam=mappedParam.doReverseMapping(nestedMapObj);
debugSerial << F("MBUSD: NestedMapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl; traceSerial << F("MBUSD: NestedMapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
if (!(lastMeasured->subtype & MB_VALUE_OUTDATED)) if (!(lastMeasured->subtype & MB_VALUE_OUTDATED))
{ {
@@ -417,39 +389,9 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
break; break;
} }
} }
/*
aJsonObject *nextRegObj = NULL;
int registerType = 0;
nextRegObj = aJson.getObjectItem(paramObj, "nextreg");
if (nextRegObj) registerType=MODBUS_HOLDING_REG_TYPE;
else
{
nextRegObj = aJson.getObjectItem(paramObj, "nextir");
if (nextRegObj) registerType=MODBUS_INPUT_REG_TYPE;
else
{
nextRegObj = aJson.getObjectItem(paramObj, "nextcoil");
if (nextRegObj) registerType=MODBUS_COIL_REG_TYPE;
else
{
nextRegObj = aJson.getObjectItem(paramObj, "nextdin");
if (nextRegObj) registerType=MODBUS_DISCRETE_REG_TYPE;
}
}
}
if (registerType && nextRegObj && (nextRegObj->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo))
{
debugSerial<<F("Recurrent searching nextreg")<<endl;
mappedParam = findRegister(nextRegObj->valueint,nextRegObj->valueint-registerFrom,registerType,registerFrom,registerTo,false,&submitRecurrentOut);
executeWithoutCheck=true;
}
else errorSerial<<F("nextreg out of range")<<endl;
*/
} }
else else
debugSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl; traceSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
} //mapping } //mapping
if (doExecution && idObj && idObj->type==aJson_Int) if (doExecution && idObj && idObj->type==aJson_Int)
@@ -481,6 +423,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
else else
{ {
lastMeasured->valueint=param; lastMeasured->valueint=param;
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
lastMeasured->subtype&=~MB_VALUE_OUTDATED; lastMeasured->subtype&=~MB_VALUE_OUTDATED;
} }
} }
@@ -495,7 +438,12 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
if (executeWithoutCheck) if (executeWithoutCheck)
{ {
if (doExecution && (submitRecurrentOut || *submitParam)) executeCommand(execObj, -1, mappedParam); if (doExecution && (submitRecurrentOut || *submitParam))
{
executeCommand(execObj, -1, mappedParam);
*submitParam=true; //if requrrent check has submit smth - report it.
}
return mappedParam; return mappedParam;
} }
@@ -505,7 +453,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V"); aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param)) if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
{ {
debugSerial<<F("MBUSD: Ignored - equal with setted val")<<endl; traceSerial<<F("MBUSD: Ignored - equal with setted val")<<endl;
*submitParam=false; *submitParam=false;
} }
else else
@@ -518,6 +466,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
} }
} }
} }
//if (submitRecurrentOut) *submitParam=true; //if requrrent check has submit smth - report it.
return mappedParam; return mappedParam;
} }
paramObj=paramObj->next; paramObj=paramObj->next;
@@ -550,7 +499,7 @@ return itemCmd();
int registerTo=aJson.getArrayItem(reg, 1)->valueint; int registerTo=aJson.getArrayItem(reg, 1)->valueint;
if (readModbus(registerFrom,regType,registerTo-registerFrom+1)) if (readModbus(registerFrom,regType,registerTo-registerFrom+1))
{ debugSerial<<endl; { traceSerial<<endl;
for(int i=registerFrom;i<=registerTo;i++) for(int i=registerFrom;i<=registerTo;i++)
{ {
findRegister(i,i-registerFrom,regType,registerFrom,registerTo); findRegister(i,i-registerFrom,regType,registerFrom,registerTo);
@@ -582,7 +531,7 @@ void out_Modbus::initLine()
node.begin(item->getArg(0), modbusSerial); node.begin(item->getArg(0), modbusSerial);
} }
int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType) int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
{ {
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;} if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
@@ -595,45 +544,118 @@ int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
{ {
regObj = aJson.getObjectItem(templateParamObj, "coil"); regObj = aJson.getObjectItem(templateParamObj, "coil");
if (!regObj) {errorSerial<<F(" internal send error - no reg/coil")<<endl; return -2;} if (!regObj) {errorSerial<<F(" internal send error - no reg/coil")<<endl; return -2;}
else regType = PAR_COIL; else outValue->subtype = PAR_COIL;
} }
if (regObj->type != aJson_Int) {errorSerial<<F(" Reg/coil must be int")<<endl; return -2;}
aJsonObject * prefetchObj = aJson.getObjectItem(templateParamObj, "prefetch");
aJsonObject *lastMeasured = NULL;
int res = -1; int res = -1;
// int8_t regType = PAR_I16; if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valuebool)
// aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type"); {
// if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring); int modbusRegType = (outValue->subtype == PAR_COIL) ? MODBUS_COIL_REG_TYPE:MODBUS_HOLDING_REG_TYPE;
debugSerial<<F("\nMBUS: prefetching ")<<paramName<<F(" #") <<regObj->valueint << " type:" << modbusRegType << " ";
switch(regType) { /// to prevent CORRUPTIOIN if using same buffer
uint16_t localBuffer;
node.setResponseBuffer(&localBuffer,1);
bool successRead = readModbus(regObj->valueint,modbusRegType,1);
if (successRead)
{
#ifdef PREFETCH_EXEC_IMMEDIALELLY
// option to execute if changed immediatelly
bool submited = false;
findRegister(regObj->valueint,0,modbusRegType,regObj->valueint,regObj->valueint,true,&submited);
node.setDefaultResponseBuffer();
if (submited)
{
debugSerial << F("MBUS:")<<paramName<< (" val changed. Write cancelled")<<endl;
return -3;
}
else debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
#else
// Option to skip writing if change, let next polling take of change
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramName);
if (execObj)
{
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child;
//Retrive previous data
lastMeasured = aJson.getObjectItem(markObj,"@S");
if (lastMeasured)
{
if (lastMeasured->type == aJson_Int)
{
traceSerial<<F(" Last:")<<lastMeasured->valueint<< F(" Now:") << localBuffer<<endl;
if (lastMeasured->valueint != localBuffer)
{
debugSerial << F("MBUS:")<<paramName<< F(" val changed.")<<endl;
node.setDefaultResponseBuffer();
return -3;
}
else
{
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
}
}
}
}
}
#endif
}
node.setDefaultResponseBuffer();
}
switch(outValue->subtype) {
case PAR_U16: case PAR_U16:
case PAR_I16: case PAR_I16:
case PAR_TENS: case PAR_TENS:
case PAR_100: case PAR_100:
res = node.writeSingleRegister(regObj->valueint,value); res = node.writeSingleRegister(regObj->valueint,outValue->valueint);
break; break;
break; break;
case PAR_I32: case PAR_I32:
case PAR_U32: case PAR_U32:
res = node.writeSingleRegister(regObj->valueint,swap(value & 0xFFFF)); res = node.writeSingleRegister(regObj->valueint,swap(outValue->valueint & 0xFFFF));
res += node.writeSingleRegister(regObj->valueint+1,swap(value >> 16)) ; res += node.writeSingleRegister(regObj->valueint+1,swap(outValue->valueint >> 16)) ;
break; break;
case PAR_U8L: case PAR_U8L:
case PAR_I8L: case PAR_I8L:
res = node.writeSingleRegister(regObj->valueint,value & 0xFF); res = node.writeSingleRegister(regObj->valueint,outValue->valueint & 0xFF);
break; break;
case PAR_U8H: case PAR_U8H:
case PAR_I8H: case PAR_I8H:
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8); res = node.writeSingleRegister(regObj->valueint,(outValue->valueint & 0xFFFF)>> 8);
break; break;
case PAR_COIL: case PAR_COIL:
res = node.writeSingleCoil (regObj->valueint,value); res = node.writeSingleCoil (regObj->valueint,outValue->valueint);
break; break;
} }
mbusSlenceTimer = millisNZ(); mbusSlenceTimer = millisNZ();
debugSerial<<F("Res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<value<<endl; debugSerial<<F("MBUS res: ")<<res<<F(" ")<<paramName<<" reg:"<<regObj->valueint<<F(" val:")<<outValue->valueint<<endl;
//If wrote - suppress action on poll
if ((res ==0) && (outValue->type == aJson_Int) && lastMeasured && (lastMeasured->type == aJson_Int)) lastMeasured->valueint = outValue->valueint;
return ( res == 0); return ( res == 0);
} }
@@ -667,14 +689,23 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
lineInitialized=true; lineInitialized=true;
initLine(); initLine();
} }
int sendRes;
int savedValue;
do
{
savedValue = outValue->valueint;
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" "; debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
switch (sendModbus(execObj->name,outValue->valueint,outValue->subtype)) sendRes = sendModbus(execObj->name,outValue);
}
while (savedValue != outValue->valueint); //repeat sending if target value changed while we're waited for mbus responce
switch (sendRes)
{ {
case 1: //success case 1: //success
execObj->subtype&=~ MB_NEED_SEND; execObj->subtype&=~ MB_NEED_SEND;
onceSendOk=true; onceSendOk=true;
///return 1; //relax ///return 1; //relax
break; break;
case 0: //fault case 0: //fault
execObj->subtype |= MB_SEND_ERROR; execObj->subtype |= MB_SEND_ERROR;
@@ -682,6 +713,11 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++; if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl; errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl;
break; break;
case -3:
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" sending cancelled")<<endl;
//outValue->valueint=
execObj->subtype&=~ MB_NEED_SEND;
break;
default: //param not found default: //param not found
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl; errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
execObj->subtype&=~ MB_NEED_SEND; execObj->subtype&=~ MB_NEED_SEND;
@@ -719,7 +755,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
// if some polling configured // if some polling configured
if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store->poolingDiscreteIns) if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store->poolingDiscreteIns)
{ {
debugSerial<<F("MBUSD: Poll ")<< item->itemArr->name << endl; traceSerial<<F("MBUSD: Poll ")<< item->itemArr->name << endl;
modbusBusy=1; modbusBusy=1;
if (!lineInitialized) if (!lineInitialized)
@@ -732,7 +768,7 @@ if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store
pollModbus(store->pollingIrs,MODBUS_INPUT_REG_TYPE); pollModbus(store->pollingIrs,MODBUS_INPUT_REG_TYPE);
pollModbus(store->pollingCoils,MODBUS_COIL_REG_TYPE); pollModbus(store->pollingCoils,MODBUS_COIL_REG_TYPE);
pollModbus(store->poolingDiscreteIns ,MODBUS_DISCRETE_REG_TYPE); pollModbus(store->poolingDiscreteIns ,MODBUS_DISCRETE_REG_TYPE);
debugSerial<<F("MBUSD: endPoll ")<< item->itemArr->name << endl; traceSerial<<F("MBUSD: endPoll ")<< item->itemArr->name << endl;
//Non blocking waiting to release line //Non blocking waiting to release line
uint32_t time = millis(); uint32_t time = millis();
@@ -768,6 +804,7 @@ int8_t regType = PAR_I16;
aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type"); aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map"); aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map");
if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring); if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
switch(regType) { switch(regType) {
case PAR_I16: case PAR_I16:
@@ -794,27 +831,21 @@ aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map");
Value=cmdValue.getTens_raw()*(100/TENS_BASE); Value=cmdValue.getTens_raw()*(100/TENS_BASE);
} }
debugSerial<<F("MBUSD: suffix:")<<suffixStr<< F(" Val: ")<<Value<<endl; traceSerial<<F("MBUSD: suffix:")<<suffixStr<< F(" Val: ")<<Value<<endl;
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2); aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object) if (itemParametersObj && itemParametersObj->type ==aJson_Object)
{ {
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr); aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr);
if (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array))) if (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array)))
{ {
/*
aJsonObject *polledValue = aJson.getObjectItem(execObj,"@S");
if (polledValue && polledValue->type == aJson_Int && (polledValue->valueint == Value))
{
debugSerial<<F("Ignored - not changed")<<endl;
}
else */
{ //Schedule update
execObj->subtype |= MB_NEED_SEND;
aJsonObject * markObj = execObj; aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child; if (execObj->type == aJson_Array) markObj = execObj->child;
//Schedule update
execObj->subtype |= MB_NEED_SEND;
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V"); aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) // Existant. Preserve original @type if (outValue) // Existant. Preserve original @type
{ {
@@ -829,15 +860,17 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
outValue = aJson.getObjectItem(markObj,"@V"); outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) outValue->subtype =regType & 0xF; if (outValue) outValue->subtype =regType & 0xF;
} }
/* Conflict with pre-fetching
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S"); aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
if (polledValue && outValue->type == aJson_Int) if (polledValue && outValue->type == aJson_Int)
{ {
traceSerial<<"MBUS: not Stored "<<Value<<" to @S of "<<item->itemArr->name<<":"<<templateParamObj->name<<endl;
polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling
polledValue->subtype&=~MB_VALUE_OUTDATED; polledValue->subtype&=~MB_VALUE_OUTDATED;
} }
*/
}
} }
} }
return 1; return 1;

View File

@@ -38,7 +38,7 @@ public:
int Stop() override; int Stop() override;
int getChanType() override; int getChanType() override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
int getDefaultStorageType(){return ST_INT32;}; //int getDefaultStorageType(){return ST_INT32;};
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override; //int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override;
protected: protected:
@@ -47,7 +47,7 @@ protected:
itemCmd findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution = true, bool * submitParam = NULL); itemCmd findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution = true, bool * submitParam = NULL);
void pollModbus(aJsonObject * reg, int regType); void pollModbus(aJsonObject * reg, int regType);
void initLine(); void initLine();
int sendModbus(char * paramName, int32_t value, uint8_t regType); int sendModbus(char * paramName, aJsonObject * outValue);
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd); int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
}; };
#endif #endif

View File

@@ -26,7 +26,7 @@ public:
int Stop() override; int Stop() override;
//int isActive() override; //int isActive() override;
int getChanType() override; int getChanType() override;
int getDefaultStorageType(){return ST_PERCENTS255;}; //int getDefaultStorageType(){return ST_PERCENTS255;};
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override; //int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;

View File

@@ -44,19 +44,19 @@ if (gatesObj /*&& aJson.getArraySize(item->itemArg)>=2*/)
} }
i=i->next; i=i->next;
} }
debugSerial << F ("MultiVent init")<< endl; debugSerial << F ("VENT: init")<< endl;
setStatus(CST_INITIALIZED); setStatus(CST_INITIALIZED);
return 1; return 1;
} }
debugSerial << F ("MultiVent config failed")<< endl; debugSerial << F ("VENT: config failed")<< endl;
return 0; return 0;
} }
int out_Multivent::Stop() int out_Multivent::Stop()
{ {
debugSerial << F ("Multivent De-Init") << endl; debugSerial << F ("VENT: De-Init") << endl;
setStatus(CST_UNKNOWN); setStatus(CST_UNKNOWN);
return 1; return 1;
} }
@@ -151,7 +151,7 @@ while (i)
if (cmdObj->valueint == CMD_OFF || cmdObj->valueint == -1) if (cmdObj->valueint == CMD_OFF || cmdObj->valueint == -1)
{ {
debugSerial<<"Turning ON"<<endl; debugSerial<<"VENT: Turning ON"<<endl;
cmdObj->valueint = CMD_ON; cmdObj->valueint = CMD_ON;
cmd.Cmd(CMD_ON); cmd.Cmd(CMD_ON);
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name); //if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
@@ -162,7 +162,7 @@ while (i)
else else
{ {
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1) if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
{ debugSerial<<"Turning OFF"<<endl; { debugSerial<<"VENT: Turning OFF"<<endl;
cmdObj->valueint = CMD_OFF; cmdObj->valueint = CMD_OFF;
cmd.Cmd(CMD_OFF); cmd.Cmd(CMD_OFF);
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name); //if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
@@ -204,10 +204,13 @@ while (i)
if (!totalV) return 0; if (!totalV) return 0;
int fanV=activeV/totalV; int fanV=activeV/totalV;
debugSerial << F("Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max request:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl; debugSerial << F("VENT: Total V:")<<totalV<<F(" active V:")<<activeV/255<< F(" fan%:")<<fanV<< F(" Max req:")<<maxRequestedV/255 <<F(" from ")<<maxV<<F(" m3")<< endl;
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF));
//executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd((fanV)?CMD_ON:CMD_OFF));
if (fanV)
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).Cmd(CMD_ON));
else
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV));
//Move gates only if fan is actually on //Move gates only if fan is actually on
if (!fanV) return 1; if (!fanV) return 1;
@@ -229,7 +232,7 @@ while (i)
{ {
int requestedV=V*setObj->valueint; int requestedV=V*setObj->valueint;
out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV; out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV;
debugSerial<<i->name<<(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl; debugSerial<<F("VENT: ")<<i->name<<F(" Req:")<<requestedV/255<<F(" Out:")<<out<<endl;
} }

View File

@@ -17,7 +17,7 @@ public:
int Stop() override; int Stop() override;
//int isActive() override; //int isActive() override;
int getChanType() override; int getChanType() override;
int getDefaultStorageType(){return ST_PERCENTS255;}; //int getDefaultStorageType(){return ST_PERCENTS255;};
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
protected: protected:
void getConfig(); void getConfig();

View File

@@ -171,7 +171,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
if (store->alarmArmed) debugSerial << F(" <ALM>"); if (store->alarmArmed) debugSerial << F(" <ALM>");
debugSerial<<endl; debugSerial<<endl;
if (((abs(store->output-store->prevOut)>OUTPUT_TRESHOLD) || (item->getFlag(FLAG_ACTION_NEEDED))) && !store->alarmArmed) if (( (NOT_FILTER_PID_OUT || (abs(store->output-store->prevOut)>OUTPUT_TRESHOLD)) || (item->getFlag(FLAG_ACTION_NEEDED))) && !store->alarmArmed)
{ {
aJsonObject * oCmd = aJson.getArrayItem(item->itemArg, 1); aJsonObject * oCmd = aJson.getArrayItem(item->itemArg, 1);
@@ -334,32 +334,38 @@ case S_CTRL:
switch (command) switch (command)
{ {
case CMD_OFF: case CMD_OFF:
//value.Percents255(0); if (isNotRetainingStatus()) executeCommand(oCmd,-1,itemCmd().Cmd(CMD_DISABLE)); // Not actually disable, just inform depended systems, that no autoreg now (for pannels indication)
executeCommand(oCmd,-1,value);
item->SendStatus(FLAG_FLAGS);
return 1;
case CMD_ON: case CMD_ON:
case CMD_HEAT: case CMD_HEAT:
case CMD_COOL: case CMD_COOL:
case CMD_AUTO: case CMD_AUTO:
case CMD_FAN: case CMD_FAN:
case CMD_DRY: case CMD_DRY:
executeCommand(oCmd,-1,value);
executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE)); executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE));
executeCommand(oCmd,-1,value);
item->SendStatus(FLAG_FLAGS); item->SendStatus(FLAG_FLAGS);
return 1; return 1;
case CMD_ENABLE: case CMD_ENABLE:
//item->setCmd(CMD_ENABLE); if (isNotRetainingStatus())
//item->SendStatus(FLAG_COMMAND); {
item->setCmd(CMD_ON);
item->SendStatus(FLAG_COMMAND);
}
item->setFlag(FLAG_ACTION_NEEDED); item->setFlag(FLAG_ACTION_NEEDED);
executeCommand(oCmd,-1,value); executeCommand(oCmd,-1,value);
if (isActive()) executeCommand(oCmd,-1,itemCmd().Cmd((CMD_ON)));
store->prevOut=-2.0; store->prevOut=-2.0;
return 1; return 1;
case CMD_DISABLE: case CMD_DISABLE:
//item->setCmd(CMD_DISABLE);
//item->SendStatus(FLAG_COMMAND);
executeCommand(oCmd,-1,value); executeCommand(oCmd,-1,value);
if (!isActive()) executeCommand(oCmd,-1,itemCmd().Cmd((CMD_OFF)));
return 1; return 1;
/* /*
case CMD_OFF: case CMD_OFF:

View File

@@ -31,7 +31,7 @@ public:
int Stop() override; int Stop() override;
int isActive() override; int isActive() override;
int getChanType() override; int getChanType() override;
int getDefaultStorageType(){return ST_FLOAT;}; //int getDefaultStorageType(){return ST_FLOAT;};
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
void alarm(bool); void alarm(bool);

View File

@@ -127,8 +127,11 @@ switch (cmd.getCmd()){
case CH_PWM: case CH_PWM:
{ short k ; { short k ;
if (authorized || !isProtectedPin(iaddr)) if (authorized || !isProtectedPin(iaddr))
{
analogWrite(iaddr, k=cmd.getPercents255(inverse)); analogWrite(iaddr, k=cmd.getPercents255(inverse));
debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<endl; debugSerial<<F("Pin:")<<iaddr<<F("=")<<k<<endl;
}
else errorSerial<<F("Pin:")<<iaddr<<F(" protected")<<endl;
return 1; return 1;
} }
case CH_RGB: case CH_RGB:

View File

@@ -43,7 +43,7 @@ if (item) item->setExt(0);
//if (item->getCmd()) item->setFlag(FLAG_COMMAND); //if (item->getCmd()) item->setFlag(FLAG_COMMAND);
//if (item->itemVal) item->setFlag(FLAG_PARAMETERS); //if (item->itemVal) item->setFlag(FLAG_PARAMETERS);
setStatus(CST_INITIALIZED); setStatus(CST_INITIALIZED);
if (item->isActive()>0) ///???? if (item && (item->isActive()>0)) ///????
{ {
item->setExt(millisNZ()); item->setExt(millisNZ());
} }

View File

@@ -64,7 +64,7 @@ public:
int Stop() override; int Stop() override;
int getChanType() override; int getChanType() override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override; int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
int getDefaultStorageType(){return ST_INT32;}; //int getDefaultStorageType(){return ST_INT32;};
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override; //int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL) override;
protected: protected:

View File

@@ -1,6 +1,10 @@
#pragma once #pragma once
#include <Arduino.h> #include <Arduino.h>
#ifndef NOT_FILTER_PID_OUT
#define NOT_FILTER_PID_OUT 1
#endif
#define DHCP_ATTEMPTS_FALLBACK 3 #define DHCP_ATTEMPTS_FALLBACK 3
#define TENS_FRACT_LEN 2 #define TENS_FRACT_LEN 2
#define TENS_BASE 100 #define TENS_BASE 100
@@ -77,16 +81,24 @@
#define TIMEOUT_REINIT 5000UL #define TIMEOUT_REINIT 5000UL
#define TIMEOUT_RELOAD 30000UL #define TIMEOUT_RELOAD 30000UL
#define TIMEOUT_RETAIN 8000UL #define TIMEOUT_RETAIN 8000UL
#define TIMEOUT_REINIT_NOT_CONFIGURED 120000UL
#define INTERVAL_1W 5000UL #define INTERVAL_1W 5000UL
#define PERIOD_THERMOSTAT_FAILED (600 * 1000UL) #define PERIOD_THERMOSTAT_FAILED (600 * 1000UL)
//#define T_ATTEMPTS 200 //#define T_ATTEMPTS 200
//#define IET_TEMP 0 //#define IET_TEMP 0
//#define IET_ATTEMPTS 1 //#define IET_ATTEMPTS 1
#ifndef THERMO_GIST_CELSIUS
#define THERMO_GIST_CELSIUS 1. #define THERMO_GIST_CELSIUS 1.
#endif
#ifndef THERMO_OVERHEAT_CELSIUS
#define THERMO_OVERHEAT_CELSIUS 38. #define THERMO_OVERHEAT_CELSIUS 38.
#endif
#ifndef FM_OVERHEAT_CELSIUS
#define FM_OVERHEAT_CELSIUS 40. #define FM_OVERHEAT_CELSIUS 40.
#endif
#ifndef MIN_VOLUME #ifndef MIN_VOLUME
#define MIN_VOLUME 20 #define MIN_VOLUME 20
@@ -120,6 +132,8 @@
#define INTERVAL_CHECK_INPUT 11 #define INTERVAL_CHECK_INPUT 11
#endif #endif
#define INTERVAL_CHECK_ULTRASONIC 100
#ifndef TIMER_CHECK_INPUT #ifndef TIMER_CHECK_INPUT
#define TIMER_CHECK_INPUT 15 #define TIMER_CHECK_INPUT 15
#endif #endif
@@ -129,7 +143,9 @@
#define INTERVAL_SLOW_POLLING 1000 #define INTERVAL_SLOW_POLLING 1000
//#define INTERVAL_POLLING 100 //#define INTERVAL_POLLING 100
#ifndef THERMOSTAT_CHECK_PERIOD
#define THERMOSTAT_CHECK_PERIOD 30000 #define THERMOSTAT_CHECK_PERIOD 30000
#endif
#ifndef OW_UPDATE_INTERVAL #ifndef OW_UPDATE_INTERVAL
#define OW_UPDATE_INTERVAL 5000 #define OW_UPDATE_INTERVAL 5000
@@ -368,6 +384,14 @@
#define PROTECTED_PINS #define PROTECTED_PINS
#endif #endif
#if not defined DEFAULT_OTA_USERNAME
#define DEFAULT_OTA_USERNAME arduino
#endif
#if not defined DEFAULT_OTA_PASSWORD
#define DEFAULT_OTA_PASSWORD password
#endif
const short protectedPins[]={PROTECTED_PINS}; const short protectedPins[]={PROTECTED_PINS};
#define protectedPinsNum (sizeof(protectedPins)/sizeof(short)) #define protectedPinsNum (sizeof(protectedPins)/sizeof(short))

View File

@@ -26,10 +26,9 @@ e-mail anklimov@gmail.com
#include "options.h" #include "options.h"
#include "main.h" #include "main.h"
#include "aJSON.h" #include "aJSON.h"
//#include "twi.h"
extern aJsonObject *owArr; extern aJsonObject *owArr;
extern uint32_t timerCtr; //extern uint32_t timerCtr;
aJsonObject *dev2Check = NULL; aJsonObject *dev2Check = NULL;
OneWire *oneWire = NULL; OneWire *oneWire = NULL;
@@ -62,7 +61,7 @@ char * getReadableNote(aJsonObject * owObj)
void processTemp(aJsonObject * owObj, float currentTemp) { void processTemp(aJsonObject * owObj, float currentTemp) {
if (!owObj || !owArr) return; if (!owObj || !owArr) return;
char* note = getReadableNote(owObj); char* note = getReadableNote(owObj);
debugSerial<<endl<<F("1WT:")<<currentTemp<<F(" <")<<owObj->name<<F("> "); debugSerial <<F("1WT:")<<currentTemp<<F(" <")<<owObj->name<<F("> ");
if ((currentTemp != -127.0) && (currentTemp != 85.0) && (currentTemp != 0.0)) if ((currentTemp != -127.0) && (currentTemp != 85.0) && (currentTemp != 0.0))
{ {
if (note) debugSerial<<note; if (note) debugSerial<<note;
@@ -127,8 +126,8 @@ int owSetup() {
if (oneWire) return true; // Already initialized if (oneWire) return true; // Already initialized
#ifdef DS2482_100_I2C_TO_1W_BRIDGE #ifdef DS2482_100_I2C_TO_1W_BRIDGE
debugSerial<<F("DS2482_100_I2C_TO_1W_BRIDGE init")<<endl; debugSerial<<F("1WT: DS2482_100_I2C_TO_1W_BRIDGE init")<<endl;
debugSerial<<F("Free:")<<freeRam()<<endl; //debugSerial<<F("Free:")<<freeRam()<<endl;
oneWire = new OneWire; oneWire = new OneWire;
#else #else
debugSerial.print(F("One wire setup on PIN:")); debugSerial.print(F("One wire setup on PIN:"));
@@ -146,7 +145,7 @@ if (!oneWire)
#ifdef DS2482_100_I2C_TO_1W_BRIDGE #ifdef DS2482_100_I2C_TO_1W_BRIDGE
Wire.begin(); Wire.begin();
if (oneWire->checkPresence()) { if (oneWire->checkPresence()) {
infoSerial.println(F("1WT: DS2482-100 present")); infoSerial.println(F("1WT: DS2482-100 present, reset"));
oneWire->deviceReset(); oneWire->deviceReset();
#ifdef APU_OFF #ifdef APU_OFF
debugSerial.println(F("APU off")); debugSerial.println(F("APU off"));
@@ -154,11 +153,11 @@ if (!oneWire)
oneWire->setActivePullup(); oneWire->setActivePullup();
#endif #endif
debugSerial.println(F("\tChecking for 1-Wire devices...")); // debugSerial.println(F("\tChecking for 1-Wire devices..."));
if (oneWire->wireReset()) if (oneWire->wireReset())
debugSerial.println(F("\tReset done")); debugSerial.println(F("1WT: Bus Reset done"));
else else
debugSerial.println(F("\tDS2482 reset error")); debugSerial.println(F("1WT: Bus reset error"));
//return true; //return true;
} }
else else
@@ -226,25 +225,25 @@ int sensors_loop(void) {
case DS2482_ERROR_CONFIG: case DS2482_ERROR_CONFIG:
errorSerial<<F("1WT: DS2482_ERROR_CONFIG")<<endl; errorSerial<<F("1WT: DS2482_ERROR_CONFIG")<<endl;
oneWire->wireReset(); i2cReset();
return INTERVAL_1W; break;
case DS2482_ERROR_TIMEOUT: case DS2482_ERROR_TIMEOUT: //Busy over time
errorSerial<<F("1WT: 1-wire shorted")<<endl; errorSerial<<F("1WT: BUSY timeout")<<endl;
oneWire->wireReset(); i2cReset();
return INTERVAL_1W; break;
default: default:
errorSerial<<F("1WT: error")<<endl; break;
oneWire->wireReset();
return INTERVAL_1W;
} }
/*
if (!oneWire->checkPresence()) if (!oneWire->checkPresence())
{ {
infoSerial.println(F("1WT: lost DS2482-100")); infoSerial.println(F("1WT: lost DS2482-100"));
i2cReset(); i2cReset();
} }
*/
#endif #endif

View File

@@ -14,7 +14,7 @@ bool textMode;
uint16_t contentType; uint16_t contentType;
public: public:
seekableStream(unsigned int size):Stream(),streamSize(size) {}; seekableStream(unsigned int size):Stream(),streamSize(size),textMode(false),contentType(0) {};
virtual bool checkPermissions(char mode) {return true;}; virtual bool checkPermissions(char mode) {return true;};
unsigned int getSize() {return streamSize;} unsigned int getSize() {return streamSize;}
void setSize (unsigned int size) {streamSize = size;}; void setSize (unsigned int size) {streamSize = size;};
@@ -22,7 +22,7 @@ virtual unsigned int seek(unsigned int _pos = 0) = 0;
virtual int open(String _filename, char mode) = 0; virtual int open(String _filename, char mode) = 0;
virtual void close() = 0; virtual void close() = 0;
virtual uint16_t getContentType() {return contentType;}; virtual uint16_t getContentType() {return contentType;};
virtual void putEOF() {if (textMode) write (EOFchar);}; virtual void putEOF() {if (textMode) {write (EOFchar);textMode=false;}};
}; };
#endif #endif

View File

@@ -28,6 +28,7 @@ Streamlog::Streamlog (SerialPortType * _serialPort, uint8_t _severity, uint8_t
{ {
serialPort=_serialPort; serialPort=_serialPort;
severity=_severity; severity=_severity;
ledPattern=_ledPattern;
} }
#endif #endif
/* /*

View File

@@ -24,10 +24,12 @@ extern uint8_t udpDebugLevel;
#define SerialPortType HardwareSerial #define SerialPortType HardwareSerial
#endif #endif
#define LOG_TRACE 9
#define LOG_DEBUG 7 #define LOG_DEBUG 7
#define LOG_INFO 6 #define LOG_INFO 6
#define LOG_ERROR 3 #define LOG_ERROR 3
#define traceSerial if (serialDebugLevel>=LOG_TRACE || udpDebugLevel>=LOG_TRACE) debugSerial
class Streamlog : public Print class Streamlog : public Print
{ {
public: public:

View File

@@ -1,3 +1,4 @@
#pragma once
#define SYSCONF_OFFSET 0 #define SYSCONF_OFFSET 0
#define EEPROM_offset_NotAlligned SYSCONF_OFFSET+sizeof(systemConfigData) #define EEPROM_offset_NotAlligned SYSCONF_OFFSET+sizeof(systemConfigData)
#define SYSCONF_SIZE EEPROM_offsetJSON #define SYSCONF_SIZE EEPROM_offsetJSON
@@ -5,7 +6,7 @@
#define MAXFLASHSTR 32 #define MAXFLASHSTR 32
#define PWDFLASHSTR 16 #define PWDFLASHSTR 16
#define EEPROM_SIGNATURE "LHC1" #define EEPROM_SIGNATURE "LHC2"
#define EEPROM_SIGNATURE_LENGTH 4 #define EEPROM_SIGNATURE_LENGTH 4
//#define EEPROM_offsetJSON IFLASH_PAGE_SIZE //#define EEPROM_offsetJSON IFLASH_PAGE_SIZE
@@ -23,12 +24,12 @@ const char EEPROM_signature[] = EEPROM_SIGNATURE;
uint32_t configFlags32bit; uint32_t configFlags32bit;
struct struct
{ {
uint8_t serialDebugLevel:3; uint8_t serialDebugLevel:4;
uint8_t notGetConfigFromHTTP:1; uint8_t notGetConfigFromHTTP:1;
uint8_t udpDebugLevel:3; uint8_t udpDebugLevel:3;
uint8_t notSaveSuccedConfig:1; uint8_t notSaveSuccedConfig:1;
uint8_t dhcpFallback:1; uint8_t dhcpFallback:1;
uint8_t spare2:7; uint8_t spare2:6;
uint16_t sysConfigHash; uint16_t sysConfigHash;
}; };
} systemConfigFlags; } systemConfigFlags;

0
lighthub/templateStr.cpp Normal file
View File

110
lighthub/templateStr.h Normal file
View File

@@ -0,0 +1,110 @@
#ifndef _TEMPLATE_STREAM_H_
#define _TEMPLATE_STREAM_H_
#include <Stream.h>
#include <aJSON.h>
#include <streamlog.h>
//#define KEYLEN 8
extern aJsonObject * topics;
class templateStream : public Stream
{
public:
templateStream(char *s, short sfx=0) : str(s), pos(0), val(NULL), valpos(0), bucket(0),suffix(sfx) {buffer[0]='\0'; }
// Stream methods
virtual int available() { return str[pos]; }
virtual int read() {
if (bucket)
{ int ch = bucket;
bucket=0;
return ch;
};
if (str[pos]=='$')
{
if (str[pos+1]=='{')
{
unsigned int i = 0;
while (str[pos+2+i] && str[pos+2+i]!='}') i++;
if (i && (str[pos+2+i]=='}'))
{
str[pos+2+i]='\0';
val=resolveKey(str+pos+2);
valpos=0;
str[pos+2+i]='}';
pos+=3+i;
}
}
}
if (val)
{
char ch = val[valpos];
if (ch)
{
valpos++;
return ch;
}
else val = NULL;
}
if (str)
{
char ch = str[pos];
if (ch)
{
pos++;
return ch;
}
else
{
str=NULL;
return 0;
}
}
else return -1;
}
virtual int peek()
{
int bucket = read();
return bucket;
}
virtual void flush() { };
// Print methods
virtual size_t write(uint8_t c) { return 0; };
virtual char * resolveKey(char *key)
{
if (topics && topics->type == aJson_Object)
{
aJsonObject *valObj = aJson.getObjectItem(topics, key);
if (valObj->type == aJson_String) return valObj->valuestring;
}
if (suffix && (suffix<suffixNum) && !strcmp(key,"sfx"))
{
//debugSerial<<F("Template: Suffix=")<<suffix<<endl;
buffer[0]='/';
strncpy_P(buffer+1,suffix_P[suffix],sizeof(buffer)-2);
return buffer;
}
return NULL;
}
private:
char *str;
unsigned int pos;
char *val;
unsigned int valpos;
int bucket;
short suffix;
char buffer[8];
};
#endif // _TEMPLATE_STREAM_H_

View File

@@ -82,17 +82,29 @@ const char on_P[] PROGMEM = "on";
*/ */
#define ON_P commands_P[CMD_ON]
#define OFF_P commands_P[CMD_OFF]
#define REST_P commands_P[CMD_RESTORE]
#define TOGGLE_P commands_P[CMD_TOGGLE]
#define HALT_P commands_P[CMD_HALT]
#define XON_P commands_P[CMD_XON]
#define XOFF_P commands_P[CMD_XOFF]
#define HEAT_P commands_P[CMD_HEAT]
#define COOL_P commands_P[CMD_COOL]
#define AUTO_P commands_P[CMD_AUTO]
#define FAN_ONLY_P commands_P[CMD_FAN]
#define DRY_P commands_P[CMD_DRY]
#define HIGH_P commands_P[CMD_HIGH]
#define MED_P commands_P[CMD_MED]
#define LOW_P commands_P[CMD_LOW]
#define ENABLE_P commands_P[CMD_ENABLE]
#define DISABLE_P commands_P[CMD_DISABLE]
#define FREEZE_P commands_P[CMD_FREEZE]
#define UNFREEZE_P commands_P[CMD_UNFREEZE]
const char ERROR_P[] PROGMEM = "ERR";
//Commands //Commands
const char ON_P[] PROGMEM = "ON";
const char OFF_P[] PROGMEM = "OFF";
const char REST_P[] PROGMEM = "REST";
const char TOGGLE_P[] PROGMEM = "TOGGLE";
const char HALT_P[] PROGMEM = "HALT";
const char XON_P[] PROGMEM = "XON";
const char XOFF_P[] PROGMEM = "XOFF";
/* /*
const char INCREASE_P[] PROGMEM = "INCREASE"; const char INCREASE_P[] PROGMEM = "INCREASE";
const char DECREASE_P[] PROGMEM = "DECREASE"; const char DECREASE_P[] PROGMEM = "DECREASE";
@@ -102,6 +114,15 @@ const char FALSE_P[] PROGMEM = "FALSE";
const char ENABLED_P[] PROGMEM = "ENABLED"; const char ENABLED_P[] PROGMEM = "ENABLED";
const char DISABLED_P[] PROGMEM = "DISABLED"; const char DISABLED_P[] PROGMEM = "DISABLED";
*/ */
/*
const char ON_P[] PROGMEM = "ON";
const char OFF_P[] PROGMEM = "OFF";
const char REST_P[] PROGMEM = "REST";
const char TOGGLE_P[] PROGMEM = "TOGGLE";
const char HALT_P[] PROGMEM = "HALT";
const char XON_P[] PROGMEM = "XON";
const char XOFF_P[] PROGMEM = "XOFF";
const char HEAT_P[] PROGMEM = "HEAT"; const char HEAT_P[] PROGMEM = "HEAT";
const char COOL_P[] PROGMEM = "COOL"; const char COOL_P[] PROGMEM = "COOL";
const static char AUTO_P[] PROGMEM = "AUTO"; const static char AUTO_P[] PROGMEM = "AUTO";
@@ -112,13 +133,15 @@ const char DRY_P[] PROGMEM = "DRY";
const char HIGH_P[] PROGMEM = "HIGH"; const char HIGH_P[] PROGMEM = "HIGH";
const char MED_P[] PROGMEM = "MEDIUM"; const char MED_P[] PROGMEM = "MEDIUM";
const char LOW_P[] PROGMEM = "LOW"; const char LOW_P[] PROGMEM = "LOW";
const char ERROR_P[] PROGMEM = "ERR";
const char ENABLE_P[] PROGMEM = "ENABLE"; const char ENABLE_P[] PROGMEM = "ENABLE";
const char DISABLE_P[] PROGMEM = "DISABLE"; const char DISABLE_P[] PROGMEM = "DISABLE";
const char FREEZE_P[] PROGMEM = "FREEZE"; const char FREEZE_P[] PROGMEM = "FREEZE";
const char UNFREEZE_P[] PROGMEM = "UNFREEZE"; const char UNFREEZE_P[] PROGMEM = "UNFREEZE";
*/
// SubTopics // SubTopics
/*
const char SET_P[] PROGMEM = "set"; const char SET_P[] PROGMEM = "set";
const char CMD_P[] PROGMEM = "cmd"; const char CMD_P[] PROGMEM = "cmd";
const char MODE_P[] PROGMEM = "mode"; const char MODE_P[] PROGMEM = "mode";
@@ -132,7 +155,7 @@ const char VAL_P[] PROGMEM = "val";
const char DEL_P[] PROGMEM = "del"; const char DEL_P[] PROGMEM = "del";
const char _RAW_P[] PROGMEM = "raw"; const char _RAW_P[] PROGMEM = "raw";
const char CTRL_P[] PROGMEM = "ctrl"; const char CTRL_P[] PROGMEM = "ctrl";
*/
/* /*
const char RPM_P[] PROGMEM = "rpm"; const char RPM_P[] PROGMEM = "rpm";
const char STATE_P[] PROGMEM = "state"; const char STATE_P[] PROGMEM = "state";

View File

@@ -25,8 +25,18 @@ e-mail anklimov@gmail.com
#include "main.h" #include "main.h"
#include "item.h" #include "item.h"
#if not defined (NOIP)
#include <PubSubClient.h> #include <PubSubClient.h>
extern PubSubClient mqttClient;
extern int8_t ethernetIdleCount;
#endif
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include "templateStr.h"
#ifdef CANDRV
#include <candriver.h>
extern canDriver LHCAN;
#endif
#ifdef CRYPT #ifdef CRYPT
#include "SHA256.h" #include "SHA256.h"
@@ -37,10 +47,6 @@ e-mail anklimov@gmail.com
#endif #endif
extern int8_t configLocked; extern int8_t configLocked;
extern int8_t ethernetIdleCount;
extern PubSubClient mqttClient;
#if defined(__SAM3X8E__) || defined(ARDUINO_ARCH_STM32) #if defined(__SAM3X8E__) || defined(ARDUINO_ARCH_STM32)
#include <malloc.h> #include <malloc.h>
@@ -104,7 +110,7 @@ return !err;
// chan is pointer to pointer to string // chan is pointer to pointer to string
// Function return first retrived integer and move pointer to position next after ',' // Function return first retrived integer and move pointer to position next after ','
long getInt(char **chan) { long getIntFromStr(char **chan) {
if (chan && *chan && **chan) if (chan && *chan && **chan)
{ {
//Skip non-numeric values //Skip non-numeric values
@@ -367,6 +373,21 @@ uint32_t ReadUniqueID( uint32_t * pdwUniqueID )
return *(uint32_t *)(IFLASH1_ADDR + 128); // dont remove: SAM defect workaround - MPU dont leave Unique Identifier mode until read flash out UID of range return *(uint32_t *)(IFLASH1_ADDR + 128); // dont remove: SAM defect workaround - MPU dont leave Unique Identifier mode until read flash out UID of range
#elif defined(ARDUINO_ARCH_STM32)
#define UID_BASE 0x1FFFF7E8
uint16_t *idBase0 = (uint16_t*)(UID_BASE);
uint16_t *idBase1 = (uint16_t*)(UID_BASE + 0x02);
uint32_t *idBase2 = (uint32_t*)(UID_BASE + 0x04);
uint32_t *idBase3 = (uint32_t*)(UID_BASE + 0x08);
pdwUniqueID[0] = *idBase0;
pdwUniqueID[1] = *idBase1;
pdwUniqueID[2] = *idBase2;
pdwUniqueID[3] = *idBase3;
return 1;
#else #else
return 0; return 0;
#endif #endif
@@ -624,12 +645,13 @@ bool executeCommand(aJsonObject* cmd, int8_t toggle)
return executeCommand(cmd,toggle,itemCmd()); return executeCommand(cmd,toggle,itemCmd());
} }
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit) bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem, aJsonObject* defaultEmit, aJsonObject* defaultCan)
//bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd) //bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd)
{ {
//char * legacyString =NULL; //char * legacyString =NULL;
aJsonObject *item = NULL; aJsonObject *item = NULL;
aJsonObject *emit = NULL; aJsonObject *emit = NULL;
aJsonObject *can = NULL;
aJsonObject *icmd = NULL; aJsonObject *icmd = NULL;
aJsonObject *ecmd = NULL; aJsonObject *ecmd = NULL;
char cmdType = 0; char cmdType = 0;
@@ -644,7 +666,7 @@ switch (cmdType)
aJsonObject * command = cmd->child; aJsonObject * command = cmd->child;
while (command) while (command)
{ {
executeCommand(command,toggle,_itemCmd,defaultItem,defaultEmit); executeCommand(command,toggle,_itemCmd,defaultItem,defaultEmit,defaultCan);
command = command->next; command = command->next;
} }
configLocked--; configLocked--;
@@ -658,8 +680,7 @@ switch (cmdType)
item = aJson.getObjectItem(cmd, "item"); item = aJson.getObjectItem(cmd, "item");
emit = aJson.getObjectItem(cmd, "emit"); emit = aJson.getObjectItem(cmd, "emit");
can = aJson.getObjectItem(cmd, "can");
switch (toggle) switch (toggle)
{ {
case 0: case 0:
@@ -683,6 +704,7 @@ switch (cmdType)
{ {
if (!item) item = defaultItem; if (!item) item = defaultItem;
if (!emit) emit = defaultEmit; if (!emit) emit = defaultEmit;
if (!can) can = defaultCan;
char * itemCommand = NULL; char * itemCommand = NULL;
char Buffer[16]; char Buffer[16];
@@ -690,8 +712,22 @@ switch (cmdType)
//else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); //else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer));
char * emitCommand; char * emitCommand;
short suffix=0;
// aJsonObject * dict=NULL;
if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring; if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring;
else emitCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); else
{
emitCommand = _itemCmd.toString(Buffer,sizeof(Buffer));
// dict = aJson.createObject();
// aJson.addStringToObject(dict, "sfx", )
suffix=_itemCmd.getSuffix();
if (!suffix)
{
if (_itemCmd.isCommand()) suffix=S_CMD;
else if (_itemCmd.isValue()) suffix = S_SET;
}
}
//debugSerial << F("IN:") << (pin) << F(" : ") <<endl; //debugSerial << F("IN:") << (pin) << F(" : ") <<endl;
if (item) { if (item) {
@@ -703,9 +739,14 @@ switch (cmdType)
#if not defined (NOIP)
if (emit && emitCommand && emit->type == aJson_String) { if (emit && emitCommand && emit->type == aJson_String) {
debugSerial << F("Emit: ")<<emit->valuestring<< F(" -> ")<<emitCommand<<endl;
templateStream ts(emit->valuestring,suffix);
char addrstr[MQTT_TOPIC_LENGTH];
//ts.setTimeout(0);
addrstr[ts.readBytesUntil('\0',addrstr,sizeof(addrstr))]='\0';
debugSerial << F("Emit: <")<<emit->valuestring<<"> "<<addrstr<< F(" -> ")<<emitCommand<<endl;
/* /*
TODO implement TODO implement
#ifdef WITH_DOMOTICZ #ifdef WITH_DOMOTICZ
@@ -720,15 +761,18 @@ switch (cmdType)
*/ */
char addrstr[MQTT_TOPIC_LENGTH];
strncpy(addrstr,emit->valuestring,sizeof(addrstr)); //strncpy(addrstr,emit->valuestring,sizeof(addrstr));
if (mqttClient.connected() && !ethernetIdleCount) if (mqttClient.connected() && !ethernetIdleCount)
{ {
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); ///ChangeMe - if no '/' in addr - template not working
debugSerial << F("MQTT: ")<<addrstr<< F(" -> ")<<emitCommand<<endl;
mqttClient.publish(addrstr, emitCommand , true); mqttClient.publish(addrstr, emitCommand , true);
} }
} // emit } // emit
#endif //NOIP
if (item && item->type == aJson_String) { if (item && item->type == aJson_String) {
//debugSerial <<F("Controlled item:")<< item->valuestring <<endl; //debugSerial <<F("Controlled item:")<< item->valuestring <<endl;
@@ -746,6 +790,16 @@ switch (cmdType)
else it.Ctrl(_itemCmd); else it.Ctrl(_itemCmd);
} }
} }
#ifdef CANDRV
if (can)
{
if (itemCommand) LHCAN.sendCommand(can, itemCmd(itemCommand));
else LHCAN.sendCommand(can, _itemCmd);
} //else debugSerial << "Exec: noCan"<< endl;
#endif
return true; return true;
} }
default: default:
@@ -807,7 +861,7 @@ serialParamType str2SerialParam(char * str)
{ {
//debugSerial<< i << F(" ") << pgm_read_word_near(&serialModes_P[i].mode)<< endl; //debugSerial<< i << F(" ") << pgm_read_word_near(&serialModes_P[i].mode)<< endl;
if (sizeof(serialModesNum)==4) if (sizeof(serialParamType)==4)
return pgm_read_dword_near(&serialModes_P[i].mode); return pgm_read_dword_near(&serialModes_P[i].mode);
else else
return pgm_read_word_near(&serialModes_P[i].mode); return pgm_read_word_near(&serialModes_P[i].mode);
@@ -880,7 +934,7 @@ bool checkToken(char * token, char * data)
bool i2cReset(){ bool i2cReset(){
debugSerial.println("I2C Reset"); debugSerial.println(F("I2C Reset"));
Wire.endTransmission(true); Wire.endTransmission(true);
#if !defined(ARDUINO_ARCH_ESP8266) #if !defined(ARDUINO_ARCH_ESP8266)
@@ -896,19 +950,22 @@ pinMode(SDA,INPUT);
pulse=!pulse; pulse=!pulse;
delay(10);//10us мкс delay(10);//10us мкс
} }
delay(20);
Wire.begin(); Wire.begin();
#ifdef DS2482_100_I2C_TO_1W_BRIDGE #ifdef DS2482_100_I2C_TO_1W_BRIDGE
if (oneWire && oneWire->checkPresence()) if (oneWire && oneWire->checkPresence())
{ {
oneWire->deviceReset(); oneWire->deviceReset();
debugSerial.println(F("1WT: DS2482 present, reset"));
#ifndef APU_OFF #ifndef APU_OFF
oneWire->setActivePullup(); oneWire->setActivePullup();
#endif #endif
if (oneWire->wireReset()) if (oneWire->wireReset())
debugSerial.println(F("\tReset done")); debugSerial.println(F("1WT: Bus Reset done"));
else else
debugSerial.println(F("\tDS2482 reset error")); debugSerial.println(F("1WT: Bus reset error"));
} }
#endif #endif
@@ -916,5 +973,8 @@ if (oneWire && oneWire->checkPresence())
return true; return true;
} }
#pragma message(VAR_NAME_VALUE(debugSerial)) #pragma message(VAR_NAME_VALUE(debugSerial))
#pragma message(VAR_NAME_VALUE(SERIAL_BAUD)) #pragma message(VAR_NAME_VALUE(SERIAL_BAUD))

View File

@@ -53,7 +53,7 @@ void PrintBytes(uint8_t* addr, uint8_t count, bool newline);
void SetBytes(uint8_t* addr, uint8_t count, char * out); void SetBytes(uint8_t* addr, uint8_t count, char * out);
bool SetAddr(char * in, uint8_t* addr); bool SetAddr(char * in, uint8_t* addr);
uint8_t HEX2DEC(char i, bool* err); uint8_t HEX2DEC(char i, bool* err);
long getInt(char ** chan); long getIntFromStr(char **chan);
itemCmd getNumber(char ** chan); itemCmd getNumber(char ** chan);
unsigned long freeRam (); unsigned long freeRam ();
void parseBytes(const char* str, char separator, byte* bytes, int maxBytes, int base); void parseBytes(const char* str, char separator, byte* bytes, int maxBytes, int base);
@@ -70,7 +70,7 @@ void softRebootFunc();
bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo = 0); bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo = 0);
//bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL); //bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL);
bool executeCommand(aJsonObject* cmd, int8_t toggle = -1); bool executeCommand(aJsonObject* cmd, int8_t toggle = -1);
bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem=NULL, aJsonObject* defaultEmit=NULL); bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem=NULL, aJsonObject* defaultEmit=NULL, aJsonObject* defaultCan = NULL);
itemCmd mapInt(int32_t arg, aJsonObject* map); itemCmd mapInt(int32_t arg, aJsonObject* map);
unsigned long millisNZ(uint8_t shift=0); unsigned long millisNZ(uint8_t shift=0);
serialParamType str2SerialParam(char * str); serialParamType str2SerialParam(char * str);

View File

@@ -193,7 +193,7 @@ monitor_speed = 115200
platform = espressif32 platform = espressif32
framework = arduino framework = arduino
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
build_type = debug ;build_type = debug
board = esp32-evb board = esp32-evb
extra_scripts = extra_script.py extra_scripts = extra_script.py
monitor_speed = 115200 monitor_speed = 115200
@@ -258,7 +258,7 @@ lib_deps =
;ArduinoMDNS ;ArduinoMDNS
;ESPmDNS ;ESPmDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
https://github.com/anklimov/arduino-CAN.git
[env:due] [env:due]
;Experimental target with universal Ethernet Library ;Experimental target with universal Ethernet Library
@@ -326,6 +326,8 @@ lib_deps =
ArduinoMDNS ArduinoMDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
rweather/Crypto rweather/Crypto
collin80/can_common
collin80/due_can
monitor_speed = 115200 monitor_speed = 115200
[env:mega2560slim] [env:mega2560slim]
@@ -521,10 +523,24 @@ lib_deps =
platform = espressif8266 platform = espressif8266
framework = arduino framework = arduino
;board = nodemcuv2 ;board = nodemcuv2
board = esp01_1m ;esp12e ESP8266 80MHz 4MB 80KB Espressif ESP8266 ESP-12E
;esp01_1m ESP8266 80MHz 1MB 80KB Espressif Generic ESP8266 ESP-01 1M
extra_scripts = extra_script.py extra_scripts = extra_script.py
board_build.ldscript = eagle.flash.1m64.ld
;upload_protocol = esptool ;;;; 1M plug ;;;
;board = esp01_1m
;board_build.ldscript = eagle.flash.1m64.ld
;;;;;;;;;;;;;;;;;;;
;;;; WEMOS D1 ;;;;;
board = d1_mini
; change microcontroller
board_build.mcu = esp8266
; change MCU frequency
board_build.f_cpu = 80000000L
upload_protocol = esptool
;;;;;;;;;;;;;;;;;;;
;build_type = debug ;build_type = debug
;monitor_filters = esp8266_exception_decoder ;monitor_filters = esp8266_exception_decoder
@@ -717,6 +733,8 @@ lib_deps =
https://github.com/khoih-prog/TimerInterrupt_Generic.git https://github.com/khoih-prog/TimerInterrupt_Generic.git
https://github.com/rlogiacco/CircularBuffer https://github.com/rlogiacco/CircularBuffer
rweather/Crypto rweather/Crypto
https://github.com/collin80/due_can.git
https://github.com/collin80/can_common.git
monitor_speed = 115200 monitor_speed = 115200
[env:controllino] [env:controllino]
@@ -897,6 +915,78 @@ lib_deps =
monitor_speed = 115200 monitor_speed = 115200
[env:stm32-noip]
platform = ststm32
board = genericSTM32F103RB
;olimexino
board_build.mcu = stm32f103rbt6
;STM32Duino
;generic_stm32f103r
;board_build.ldscript=ldscripts\stm32f103rb_bootloader.ld
board_build.f_cpu = 72000000L
framework = arduino
;board_build.core = maple
;board_build.core = maple // STM32Duino (DEFAULT) // STM32L0
;board_build.core = stm32lo
;monitor_dtr = 1
upload_protocol = serial
;debug_tool = cmsis-dap
build_flags = !python get_build_flags.py stm32-noip
lib_ignore =
;DS2482_OneWire //UNCOMMENT for software 1-wire driver
DHT sensor library for ESPx
DmxDue
DueFlashStorage
ESPDMX
ESP-Dmx
WifiManager
FastLED
UIPEthernet
DMXSerial
DmxSimple
httpClient
SD
PrintEx
Ethernet2
Artnet
Ethernet3
WebServer
ESP_EEPROM
DHT sensor library
DallasTemperature
Adafruit Unified Sensor
DS2482_OneWire
ModbusMaster
Syslog
NRFFlashStorage
ClosedCube HDC1080
SparkFun CCS811 Arduino Library
M5Stack
ArduinoOTA
lib_deps =
EEPROM
https://github.com/anklimov/aJson
https://github.com/anklimov/CmdArduino
; ArduinoHttpClient
; https://github.com/anklimov/pubsubclient.git
Streaming
; Ethernet
Adafruit NeoPixel
Adafruit MCP23017 Arduino Library
Adafruit BusIO
SPI
br3ttb/PID@^1.2.1
; ArduinoMDNS
https://github.com/khoih-prog/TimerInterrupt_Generic.git
;https://github.com/anklimov/ModbusMaster
pazi88/STM32_CAN
ericksimoes/Ultrasonic
monitor_speed = 115200
; Run the following command to upload with this environment ; Run the following command to upload with this environment
; pio run -e Upload_ISP -t upload ; pio run -e Upload_ISP -t upload
[env:Upload_ISP] [env:Upload_ISP]