55 Commits

Author SHA1 Message Date
4769f57f07 avoid opposite cmd scheduling for no-suffix-group cmd 2025-08-31 00:50:09 +03:00
2c601b2c03 input fix for mixed configs & repeat flag, comments 2025-08-23 23:26:05 +03:00
5294617455 Fake "alarm off" event for legacy thermostat fixed
scheduled execution fixed
Aircon  driver relability improvement (working on 1-way lines)
2025-08-11 23:44:58 +03:00
d71499442e Important Input re-intrance bug fixed
Haier AC relability improved (buffer not save if incoming packet broken)
CAN - sub-item calculation fixed
continue working on MultiAC
config for LH board testing shared
2025-06-26 14:07:23 +03:00
9989e3db21 Multivent->MultiAC alpha
MEGA env migrated to universal Wiznet driver
some important core fixes
2025-05-11 23:50:32 +03:00
53c5748c14 AC CRC fix
syslog auto suspending when no ARP responce
optiboot env slimming
generic 2560 environment (any eth)
2025-05-02 00:45:49 +03:00
5480412f1b Merge branch 'master' of https://github.com/anklimov/lighthub 2025-05-01 20:34:00 +03:00
575e05cd84 RE optional 2025-05-01 20:31:31 +03:00
AnK
d6768ab594 bins 2025-04-30 01:35:23 +03:00
AnK
8754a35cba cross compilation 2025-04-30 01:14:55 +03:00
65c07a1881 group scheduling reworked 2025-04-28 22:26:36 +03:00
c2c863b8bd "activate" cmd to switch RE sections by other INs 2025-04-28 01:13:09 +03:00
5aec014767 Driver refactoring & core fixes
CAN fixes and extension
stm32 timer
2025-04-26 16:29:09 +03:00
c9714ef982 Rotary Encoder - chaning config section
input - regress fix
MBUS - logginng fix
2025-04-19 23:25:39 +03:00
2b5b780586 some Cleanup
Mbus logging fix
Rotary Encoder input (1-st success^ to be continued)
new JSON routines
Multivent to Multi AC - interim, to be continued
2025-04-14 00:45:38 +03:00
e803d1ae51 mapping val bondaries added
timer tuning
more logging to thermostat & map
MBUS chan stop if not configured well
2025-04-06 22:46:44 +03:00
6cba90f7dd timer refactoring
INCREASE/DECREASE postref fix
mbus write if not configured corruption fixed
2025-03-20 00:33:18 +03:00
6019aa41bb MBUS refactoring,
AC Haier tolerance for comm errors(CRC check),
MERCURY - not blocking MBUS if failed (delay added if login fail)
Kernel fixes (flags, Locks)
Multivent to multichannel virtual AC converted (interim)
PID library forked and changed
2025-01-22 02:18:25 +03:00
891b029501 less CAN logging
DISABLE for group channel (disarming) reguire signature
trace level logging fixed
esp32 = changed compilation options
2024-11-04 22:48:50 +03:00
fae1bd4dcc pre-rel bins 2024-08-23 18:59:58 +03:00
e5e24943a6 critical relability fix 2024-08-23 18:35:39 +03:00
f672878873 pre-release-binaries 2024-08-23 00:30:59 +03:00
ff8997fb02 post-refactoring fixes: $command, Items-Parse 2024-08-23 00:12:12 +03:00
96a9c59add nrf bin 2024-08-22 00:56:21 +03:00
7759d51b31 Cross comp & binaries 2024-08-22 00:55:31 +03:00
e21541aa7a cleanup and odd cleanConf fix 2024-08-22 00:35:47 +03:00
806e99eb92 NO-IP devices persistence
STM Flash cfg fix
 CAN GROUP chan fix
 CRC16 fix
2024-08-21 14:01:06 +03:00
2b638b1310 MQTT->CAN proxy. CRC16 for CAN config 2024-08-19 22:35:20 +03:00
82f729216e mapping constrain fix & more mbus relability 2024-08-16 21:41:13 +03:00
dc6e310b10 MBUS fix for requrent def# reg less main reg
Now it can working for empty action for def# reg
2024-08-15 00:36:14 +03:00
baad75fde7 bins 2024-08-14 20:04:11 +03:00
7040d9bf93 MBUS no write if prefetched value == target
Removed constrain 255 for mapping
2024-08-14 19:43:24 +03:00
0a4e70479b Modbus attempts counter reset & silence timer fix 2024-08-14 00:00:22 +03:00
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
117 changed files with 58840 additions and 69951 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)
* [Compiling and flashing](https://github.com/anklimov/lighthub/wiki/Compiling-and-flashing)
* [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)
* [OpenHab integration](https://github.com/anklimov/lighthub/wiki/OpenHab--integration)
* [Doxygen developers documentation](https://anklimov.github.io/lighthub/docs/html/index.html)

View File

@@ -17,3 +17,4 @@
-DRESTART_LAN_ON_MQTT_ERRORS
-DOTA_PORT=80
-DMERCURY_ENABLE
-D ROTARYENCODER

View File

@@ -1,3 +1,4 @@
#
-DWIFI_ENABLE
-DDMX_DISABLE
# - exeption in DMX.update/begin
@@ -12,7 +13,7 @@
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
#- ArduinoMDNS didnt working
-D CANDRV
-DMCP23017
-DMODBUS_TX_PIN=13
#-DARTNET_ENABLE - udp rx errors ((
@@ -58,3 +59,4 @@
-D CORS=\"*\"
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
#-DMERCURY_ENABLE
-D ROTARYENCODER

View File

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

View File

@@ -41,3 +41,4 @@
-D MERCURY_ENABLE
#-D IPMODBUS
-D CONFIG_CLEAN_PIN=2
-D ROTARYENCODER

View File

@@ -6,13 +6,17 @@
-DCOUNTER_DISABLE
-DSPILED_DISABLE
-DAC_DISABLE
-DHSV_DISABLE
-DPWM_DISABLE
-DM5STACK
#-DSYSLOG_ENABLE
-DUSE_1W_PIN=16
#-DPID_DISABLE
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
-DMCP23017
#-DMCP23017
-DPID_DISABLE
-DNO_HOMIE
-DFS_STORAGE
-DFS_PREPARE

View File

@@ -1,4 +1,4 @@
-DWiz5500
#-DWiz5500
#-DMODBUS_SERIAL_PARAM=SERIAL_8E1
-DAVR_DMXOUT_PIN=18
-DSYSLOG_ENABLE
@@ -10,6 +10,7 @@
-DCSSHDC_DISABLE
-DSPILED_DISABLE
-DAC_DISABLE
-DOTA
-DRESTART_LAN_ON_MQTT_ERRORS

View File

@@ -18,7 +18,10 @@
-DMULTIVENT_DISABLE
#-DWiz5100
-DARDUINO_OTA_MDNS_DISABLE
-DMDNS_ENABLE
#-DMDNS_ENABLE
-DHSV_DISABLE
-DPWM_DISABLE
-DRESTART_LAN_ON_MQTT_ERRORS
-D CORS=\"*\"

View File

@@ -17,3 +17,4 @@
-D CORS=\"*\"
-D REDIRECTION_URL=\"http://lazyhome.ru/pwa\"
#-DMERCURY_ENABLE
-D ROTARYENCODER

View File

@@ -12,6 +12,8 @@
-DENABLE_HWSERIAL1
-DdebugSerialPort=Serial1
-D TIMER_INT
#-DFLASH_BASE_ADDRESS
#-DFLASH_DATA_SECTOR
@@ -38,3 +40,4 @@
#HAL_SD_MODULE_DISABLED
#HAL_DAC_MODULE_DISABLED
#-DMERCURY_ENABLE
-D ROTARYENCODER

View File

@@ -0,0 +1,49 @@
-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
-D TIMER_INT
-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
-D ROTARYENCODER

View File

@@ -1,27 +0,0 @@
#! /bin/bash
# usage:
# first make your own copy of template
# cp build_flags_template.sh my_build_flags.sh
# then edit, change or comment something
# nano my_build_flags.sh
# and source it
# source my_build_flags.sh
echo "==============================================Custom build flags are:====================================================="
export FLAGS="-DMY_CONFIG_SERVER=lazyhome.ru"
export FLAGS="$FLAGS -DWATCH_DOG_TICKER_DISABLE"
export FLAGS="$FLAGS -DUSE_1W_PIN=12"
export FLAGS="$FLAGS -DSD_CARD_INSERTED"
export FLAGS="$FLAGS -DSERIAL_BAUD=115200"
export FLAGS="$FLAGS -DWiz5500"
export FLAGS="$FLAGS -DDISABLE_FREERAM_PRINT"
export FLAGS="$FLAGS -DCUSTOM_FIRMWARE_MAC=de:ad:be:ef:fe:00"
export FLAGS="$FLAGS -DDMX_DISABLE"
export FLAGS="$FLAGS -DMODBUS_DISABLE"
export FLAGS="$FLAGS -DOWIRE_DISABLE"
export FLAGS="$FLAGS -DAVR_DMXOUT_PIN=18"
export FLAGS="$FLAGS -DLAN_INIT_DELAY=2000"
export FLAGS="$FLAGS -DCONTROLLINO"
export PLATFORMIO_BUILD_FLAGS="$FLAGS"
echo PLATFORMIO_BUILD_FLAGS=$PLATFORMIO_BUILD_FLAGS
echo "==============================================Custom build flags END====================================================="
unset FLAGS

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: =%
..\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

View File

@@ -0,0 +1,2 @@
#!/bin/sh
../tools/mac/arduinoOTA -address 192.168.11.10 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch

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.usbmodem141101
export PORT=cu.usbmodem142401
echo . | stty -f /dev/$PORT speed 1200
../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.200 -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

View File

@@ -1 +1 @@
../tools/mac/tool-avrdude/avrdude -C ../tools/mac/tool-avrdude/avrdude.conf -P net:192.168.88.2:23000 -v -V -patmega2560 -cwiring -b115200 -D -Uflash:w:firmware.hex:i
avrdude -P net:192.168.88.2:23000 -v -V -patmega2560 -cwiring -b115200 -D -Uflash:w:firmware.hex:i

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

@@ -11,5 +11,5 @@ cp ../.pio/build/esp32-wifi/firmware.bin esp32-wifi
cp ../.pio/build/stm32-enc2860/firmware.bin stm32-enc2860
cp ../.pio/build/esp8266-wifi/firmware.bin esp8266-wifi
cp ../.pio/build/lighthub21/firmware.bin lighthub21
cp ../.pio/build/mega2560-5500/firmware.hex mega2560-5500
cp ../.pio/build/mega2560/firmware.hex mega2560
cp ../.pio/build/stm32/firmware.* stm32

View File

@@ -0,0 +1,221 @@
{
"dmx":[3,60],
"mqtt":["lh22-test","192.168.11.4"],
"dmxin":["led5","led6","led7","led8"],
"topics":{"root":"test2"},
"syslog":["192.168.88.2"],
"ow":{
"282F7E81E3713C59":{"emit":"t_1"}
},
"modbus":
{
"s8":{
"poll":{"irs":[[0,3]],"regs":[[0,1],31],"delay":11000},
"par":{
"co2":{"ir":3},
"meterStat":{"ir":0},
"alarmStat":{"ir":1},
"hr1":{"reg":0},
"hr2":{"reg":1},
"hr32":{"reg":31}
}
},
"term":{
"poll":{"regs":[0],"delay":12000},
"par":{
"t":{"reg":0,"type":"x10"}
}
},
"thmeter":{
"serial":"8N1",
"baud":4800,
"poll":{"regs":[[0,1],[2000,2001],[80,81]],"delay":3000},
"par":{
"hum" :{"reg":0,"type":"x10"},
"temp" :{"reg":1,"type":"x10"},
"slaveid" :{"reg":2000},
"baud" :{"reg":2001},
"tcalib":{"reg":80,"type":"x10"},
"hcalib":{"reg":81,"type":"x10"}
}
},
"panel":{
"serial":"8E1",
"poll":{"regs":[[39993,40008],[30000,30001]],"delay":5000},
"par":{
"fanspeed" :{"reg":40000,"prefetch":true,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
"settemp" :{"reg":40002,"prefetch":true,"id":12},
"alm01":{"reg":40004,"id":13},
"alm17":{"reg":40005,"id":14},
"alm33":{"reg":40006,"id":15},
"sethum" :{"reg":40007,"prefetch":true,"id":16},
"setvoc" :{"reg":40008,"prefetch":true,"map":{"val":[400,2000,0,100]},"id":17},
"roomtemp" :{"reg":30000,"type":"x10"},
"hum" :{"reg":30001},
"voc" :{"reg":30002},
"ch_temp" :{"reg":40009,"type":"x10","id":3},
"ext_temp" :{"reg":40010,"type":"x10","id":18},
"out_temp" :{"reg":40011,"type":"x10","id":19},
"floor_temp" :{"reg":40012,"type":"x10","id":20},
"ch_hum" :{"reg":40013,"id":28},
"heat_pwr":{"reg":40014,"id":29},
"extvoc":{"reg":40015,"map":{"val":[400,2000,0,100]},"id":27},
"actemp":{"reg":40016,"type":"x10","id":25},
"fanlvl":{"reg":40017,"id":21},
"floormode":{"reg":39995,"prefetch":true,"id":22},
"setfloor":{"reg":39996,"prefetch":true,"id":23},
"humpwr":{"reg":39998,"prefetch":true,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null},"id":24},
"fanauto":{"reg":39999,"prefetch":true,"map":{"cmd":[["ENABLE",1],["DISABLE",0],["AUTO",1]],"val":null},"id":7},
"acsettemp":{"reg":39994,"prefetch":true,"id":26},
"acon":{"reg":40003,"prefetch":true,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
"acmode" :{"reg":40001,"prefetch":true,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
"acfanauto":{"reg":39993,"prefetch":true,"map":{"cmd":[0,["AUTO",1]],"val":null,"def":39997},"id":2},
"acfan":{"reg":39997,"prefetch":true,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2]]},"id":2},
"y":{"reg":65512},
"mo":{"reg":65513},
"d":{"reg":65514},
"dw":{"reg":65515},
"h":{"reg":65516},
"m":{"reg":65517},
"s":{"reg":65518},
"blmind":{"reg":50051},
"blmaxd":{"reg":50052},
"blminn":{"reg":50053},
"blmaxn":{"reg":50054}
}
}
},
"items": {
"th":[14,[1,"thmeter",
{
"temp":{"emit":"temp","@S":null},
"hum" :{"emit":"zal2hum","@S":null},
"slaveid" :{"emit":"slaveid"},
"baud" :{"emit":"baud"},
"tcalib":{"emit":"tcalib"},
"hcalib":{"emit":"hcalib"}
}
]],
"pout0":[6,22],
"pout1":[6,23],
"pout2":[6,24],
"pout3":[6,25],
"pout4":[3,9],
"pout5":[3,8],
"pout6":[3,11],
"pout7":[3,12],
"pwm0" :[3,4],
"pwm1" :[3,5],
"pwm2" :[3,6],
"pwm3" :[3,7],
"unprot0":[6,33],
"unprot1":[6,32],
"unprot2":[6,31],
"unprot3":[6,30],
"unprot4":[6,29],
"unprot5":[6,28],
"unprot6":[6,27],
"unprot7":[6,26],
"led": [1,1],
"led2":[1,5],
"led3":[1,9],
"led4":[1,13],
"led5":[1,17],
"led6":[1,21],
"led7":[1,25],
"led8":[1,29],
"dimmer" :[0,33],
"dimmer2":[0,34],
"dimmer3":[0,35],
"dimmer4":[0,36],
"dimmer5":[0,37],
"dimmer6":[0,38],
"dimmers":[7,["dimmer","dimmer2","dimmer3","dimmer4","dimmer5","dimmer6"]],
"leds":[7,["led","led2","led3","led4","led5","led6"]],
"mbuses":[7,["mbusdim1","mbusdim2","mbusdim3","mbusdim4"]],
"all":[7,["dimmers","uouts","relays","leds"]],
"relays":[7,["pout0","pout1","pout2","pout3","pout4","pout5","pout6","pout7"]],
"uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]]
},
"in":{
"42":{"emit":"in0"},
"44":{"emit":"in1"},
"46":{"emit":"in2"},
"49":{"emit":"in3"},
"43":{"emit":"in4"},
"45":{"emit":"in5"},
"47":{"emit":"in6"},
"48":{"emit":"in7"},
"34":{"emit":"in8"},
"36":{"emit":"in9"},
"38":{"emit":"in10"},
"40":{"emit":"in11"},
"35":{"emit":"in12"},
"37":{"emit":"in13"},
"39":{"emit":"in14"},
"41":{"emit":"in15"},
"54":{"T":64,"emit":"a00","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
"55":{"T":64,"emit":"a01","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"},
"56":{"T":64,"emit":"a02","map":[0,1024,0,1024,10]},
"57":{"T":64,"emit":"a03","map":[0,1024,0,1024,10]},
"58":{"T":64,"emit":"a04","map":[0,1024,0,1024,10]},
"59":{"T":64,"emit":"a05","map":[0,1024,0,1024,10]},
"60":{"T":64,"emit":"a06"},
"61":{"T":64,"emit":"a07","map":[0,1024,0,1024,5]},
"62":{"T":64,"emit":"a08","map":[0,1024,0,1024,5]},
"63":{"T":64,"emit":"a09","map":[0,1024,0,1024,5]},
"64":{"T":64,"emit":"a10","map":[0,1024,0,1024,5]},
"65":{"T":64,"emit":"a11","map":[0,1024,0,1024,5]},
"66":{"T":2,"emit":"d12"},
"67":{
"T":2,
"scmd":{"emit":"d13","ecmd":"scmd"},
"rcmd":{"emit":"d13","ecmd":"rcmd"},
"lcmd":{"emit":"d13","ecmd":"lcmd"},
"click":{"emit":"d13","ecmd":"click"},
"dclick":{"emit":"d13","ecmd":"dclick"},
"tclick":{"emit":"d13","ecmd":"tclick"},
"scmd2":{"emit":"d13","ecmd":"scmd2"},
"scmd3":{"emit":"d13","ecmd":"scmd3"},
"lcmd2":{"emit":"d13","ecmd":"lcmd2"},
"lcmd3":{"emit":"d13","ecmd":"lcmd3"},
"rpcmd":{"emit":"d13","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d13","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d13","ecmd":"rpcmd3"}
},
"68":{"T":2,
"scmd":{"emit":"d14","ecmd":"scmd"},
"rcmd":{"emit":"d14","ecmd":"rcmd"},
"lcmd":{"emit":"d14","ecmd":"lcmd"},
"click":{"emit":"d14","ecmd":"click"},
"dclick":{"emit":"d14","ecmd":"dclick"},
"tclick":{"emit":"d14","ecmd":"tclick"},
"scmd2":{"emit":"d14","ecmd":"scmd2"},
"scmd3":{"emit":"d14","ecmd":"scmd3"},
"lcmd2":{"emit":"d14","ecmd":"lcmd2"},
"lcmd3":{"emit":"d14","ecmd":"lcmd3"},
"rpcmd":{"emit":"d14","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d14","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d14","ecmd":"rpcmd3"}
},
"69":{"T":2,
"scmd":{"emit":"d15","ecmd":"scmd"},
"rcmd":{"emit":"d15","ecmd":"rcmd"},
"lcmd":{"emit":"d15","ecmd":"lcmd"},
"click":{"emit":"d15","ecmd":"click"},
"dclick":{"emit":"d15","ecmd":"dclick"},
"tclick":{"emit":"d15","ecmd":"tclick"},
"scmd2":{"emit":"d15","ecmd":"scmd2"},
"scmd3":{"emit":"d15","ecmd":"scmd3"},
"lcmd2":{"emit":"d15","ecmd":"lcmd2"},
"lcmd3":{"emit":"d15","ecmd":"lcmd3"},
"rpcmd":{"emit":"d15","ecmd":"rpcmd"},
"rpcmd2":{"emit":"d15","ecmd":"rpcmd2"},
"rpcmd3":{"emit":"d15","ecmd":"rpcmd3"}
}
}
}

View File

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

View File

@@ -19,8 +19,8 @@ public:
protected:
virtual int publishTopic(const char* topic, long value, const char* subtopic = NULL);
virtual int publishTopic(const char* topic, float value, const char* subtopic = NULL );
virtual int publishTopic(const char* topic, const char * value, const char* subtopic = NULL);
//friend Input;
int publishTopic(const char* topic, long value, const char* subtopic = NULL);
int publishTopic(const char* topic, float value, const char* subtopic = NULL );
int publishTopic(const char* topic, const char * value, const char* subtopic = NULL);
};

View File

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

View File

@@ -1,8 +1,9 @@
#include "item.h"
#include "abstractout.h"
#include "itemCmd.h"
#include "Arduino.h"
#include "textconst.h"
int abstractOut::isActive()
{itemCmd st;
@@ -38,3 +39,38 @@ void abstractOut::setStatus(uint8_t status)
{
if (item && item->itemArr) item->itemArr->subtype = status & 0xF;
}
int abstractOut::pubAction(bool state)
{
char subtopic[10]="/";
char val[10];
strcat_P(subtopic,action_P);
short cmd=item->getCmd();
if (state)
switch(cmd)
{
case CMD_COOL:
strcpy_P(val,cooling_P);
break;
//case CMD_AUTO:
//case CMD_HEAT:
//case CMD_ON:
//
// break;
case CMD_DRY:
strcpy_P(val,drying_P);
break;
case CMD_FAN:
strcpy_P(val,fan_P);
break;
default:
strcpy_P(val,heating_P);
}
else //turned off
if (cmd==CMD_OFF) strcpy_P(val,off_P);
else strcpy_P(val,idle_P);
return publishTopic(item->itemArr->name,val,subtopic);
}

View File

@@ -7,7 +7,9 @@ class Item;
class chPersistent {};
class abstractOut : public abstractCh{
public:
abstractOut(Item * _item):abstractCh(){item=_item;};
//abstractOut(Item * _item):abstractCh(){item=_item;};
abstractOut():item(NULL){};
virtual void link(Item * _item){item=_item;};
virtual int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) =0;
virtual int isActive();
virtual bool isAllowed(itemCmd cmd){return true;};
@@ -17,6 +19,10 @@ public:
virtual int Status() override;
virtual void setStatus(uint8_t status) override;
int Setup() override;
Item * getItem() {return item;}
protected:
int pubAction(bool state);
Item * item;
};

1166
lighthub/candriver.cpp Normal file

File diff suppressed because it is too large Load Diff

238
lighthub/candriver.h Normal file
View File

@@ -0,0 +1,238 @@
#pragma once
#define NO_SUBITEM 63
#define SUBITEM_IS_COMMAND 0x20
#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;canConfigObj=NULL;canRemoteConfigObj=NULL;confCRC=0xFFFF;};
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);
aJsonObject * findConfbyName(char* devName, int * devAddr=NULL);
#if not defined (NOIP)
bool subscribeTopics(char * root, size_t buflen);
#endif
uint8_t getControllerID(){return controllerId;};
uint8_t getIdByMac(macAddress mac);
aJsonObject * canConfigObj;
aJsonObject * canRemoteConfigObj;
uint16_t confCRC;
datagram_t RXpacket;
canid_t RXid;
uint8_t RXlen;
private:
aJsonObject * getConfbyID(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

@@ -9,7 +9,9 @@
class colorChannel : public abstractOut {
public:
colorChannel(Item * _item):abstractOut(_item) {
colorChannel():iaddr(0),numArgs(0) {};
void link (Item * _item) {
abstractOut::link(_item);
iaddr = item->getArg(); //Once retrieve and store base address
if (iaddr<0) iaddr=-iaddr;
numArgs = item->getArgCount(); // and how many addresses is configured

View File

@@ -272,10 +272,11 @@ for (short rgbwChan=0; rgbwChan < RGBWChannels; rgbwChan++)
}
}
//#ifdef _dmxout
//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
//debugSerial.println();
//#endif
#ifdef _dmxout
debugSerial.print(F("DMXIN:"));
for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");}
debugSerial.println();
#endif
#endif
}
@@ -302,6 +303,7 @@ void DMXinSetup(int channels)
if (channels>(32*4)) channels = 32*4;
DMXin = new uint8_t [channels];
DMXINChannels=channels;
// debugSerial<<F("DMXIN: init chans:")<<channels<<endl;
#if defined(ARDUINO_ARCH_AVR)
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"));

View File

@@ -287,6 +287,10 @@ NRFFlashStorage EEPROM;
putEOF();
debugSerial<<F("EOF")<<endl;
}
#if defined (ARDUINO_ARCH_STM32)
eeprom_buffer_flush();
#endif
#if defined(__SAM3X8E__)
if (samBufferPos) flush();
#endif

View File

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

View File

@@ -1,4 +1,4 @@
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,7 +21,9 @@ e-mail anklimov@gmail.com
#include "inputs.h"
#include "item.h"
#include "utils.h"
#if not defined (NOIP)
#include <PubSubClient.h>
#endif
#include "main.h"
#include "itemCmd.h"
@@ -33,12 +35,26 @@ e-mail anklimov@gmail.com
#endif
#endif
#ifdef CANDRV
#include <candriver.h>
extern canDriver LHCAN;
#endif
#ifdef MCP23017
#include "Adafruit_MCP23X17.h"
Adafruit_MCP23X17 mcp;
#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;
#endif
extern aJsonObject *root;
extern int8_t ethernetIdleCount;
extern int8_t configLocked;
@@ -99,6 +115,7 @@ void Input::Parse(aJsonObject * configObj)
store = NULL;
inType = 0;
pin = 0;
pin2 =0;
if (!inputObj || !root) return;
if (!configObj) configObj = inputObj;
@@ -110,27 +127,51 @@ void Input::Parse(aJsonObject * configObj)
if (itemBuffer) inType = static_cast<uint8_t>(itemBuffer->valueint);
itemBuffer = aJson.getObjectItem(configObj, "#");
if (itemBuffer) pin = static_cast<uint8_t>(itemBuffer->valueint);
if (itemBuffer)
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))
pin2 = static_cast<uint8_t>(itemBuffer->child->child->valueint);
}
} //switch
else pin = static_cast<uint8_t>(atoi(configObj->name));
store = (inStore *) &inputObj->valueint;
}
// Persistant storage
itemBuffer = aJson.getObjectItem(inputObj, "@S");
if (!itemBuffer) {
debugSerial<<F("In: ")<<pin<<F("/")<<inType<<endl;
aJson.addNumberToObject(inputObj, "@S", (long int) 0);
itemBuffer = aJson.getObjectItem(inputObj, "@S");
}
if (itemBuffer) store = (inStore *) &itemBuffer->valueint;
void Input::stop()
{
if (!inputObj || !root || inputObj->type != aJson_Object) return;
#ifdef ROTARYENCODER
aJsonObject *itemBuffer;
itemBuffer = aJson.getObjectItem(inputObj, "#");
if (inType == IN_RE && itemBuffer && itemBuffer->valuestring && itemBuffer->type == aJson_Array)
{
delete (RotaryEncoder *) itemBuffer->valuestring;
itemBuffer->valuestring = NULL;
debugSerial<<F("RE: deleted")<<endl;
}
#endif
}
void cleanStore(aJsonObject * input)
{
if (input->type == aJson_Object) {
if (input && (input->type == aJson_Object)) {
// Check for nested inputs
Input in(input);
in.store->aslong = 0;
aJsonObject * inputArray = aJson.getObjectItem(input, "act");
if (inputArray && (inputArray->type == aJson_Array))
if (inputArray && (inputArray->type == aJson_Array || inputArray->type == aJson_Object))
{
aJsonObject *inputObj = inputArray->child;
@@ -145,21 +186,43 @@ if (input->type == aJson_Object) {
}
else
{
Input in(input);
in.Poll(CHECK_INPUT);
// Input in(input);
// in.store->aslong = 0;
}
}
}
void Input::setupRotaryEncoder()
{
#ifdef ROTARYENCODER
aJsonObject *itemBuffer;
if (!inputObj || !root || inputObj->type != aJson_Object) return;
itemBuffer = aJson.getObjectItem(inputObj, "#");
if (itemBuffer && !itemBuffer->valuestring && itemBuffer->type == aJson_Array)
{
int pin1 = getIntFromJson(itemBuffer,1,-1);
int pin2 = getIntFromJson(itemBuffer,2,-1);
int mode = getIntFromJson(itemBuffer,3,(int)RotaryEncoder::LatchMode::FOUR3);
if (pin1>=0 && pin2>=0)
{
itemBuffer->valuestring = ( char *) new RotaryEncoder(pin1, pin2, (RotaryEncoder::LatchMode)mode);
debugSerial<<F("RE: configured on pins ")<<pin1<<","<<pin2<< F(" Mode:")<<mode <<endl;
}
}
#endif
}
void Input::setup()
{
if (!isValid() || (!root)) return;
cleanStore(inputObj);
debugSerial<<F("In: ")<<pin<<F("/")<<inType<<endl;
store->aslong=0;
uint8_t inputPinMode = INPUT; //if IN_ACTIVE_HIGH
switch (inType)
{
case IN_RE:
setupRotaryEncoder();
case IN_PUSH_ON:
case IN_PUSH_TOGGLE :
inputPinMode = INPUT_PULLUP;
@@ -222,7 +285,7 @@ switch (inType)
}
int Input::Poll(short cause) {
aJsonObject * itemBuffer;
if (!isValid()) return -1;
#ifndef CSSHDC_DISABLE
in_ccs811 _ccs811(this);
@@ -256,8 +319,27 @@ switch (cause) {
case IN_CCS811:
case IN_HDC1080:
break;
#ifdef ROTARYENCODER
case IN_RE:
itemBuffer = aJson.getObjectItem(inputObj, "#");
if (inputObj && inputObj->type == aJson_Object && itemBuffer && itemBuffer->type == aJson_Array && itemBuffer->valuestring)
{
((RotaryEncoder *) itemBuffer->valuestring) ->tick();
contactPoll(cause, ((RotaryEncoder *) itemBuffer->valuestring));
}
#endif
}
break;
#ifdef ULTRASONIC
case CHECK_ULTRASONIC:
switch (inType)
{
case IN_ULTRASONIC:
analogPoll(cause);
contactPoll(cause);
}
break;
#endif
case CHECK_SENSOR: //Slow polling
switch (inType)
{
@@ -517,18 +599,101 @@ debugSerial << F("IN:") << pin << F(" DHT22 type. T=") << temp << F("°C H=") <<
setNextPollTime(millis());
}
#endif
// To Be Refactored - move to Execute after class Input inheritation on abstract chan
bool Input::checkInstructions(aJsonObject * obj)
{
aJsonObject *gotoObj = aJson.getObjectItem(obj, "activate");
if (gotoObj)
switch (gotoObj->type)
{ case aJson_Array:
{
char * name = getStringFromJson(gotoObj,0);
if (name)
{
Input in (name);
debugSerial<<"IN: "<<name<< " is "<<in.isValid()<<endl;
if (in.isValid()) return in.setCurrentInput(aJson.getArrayItem(gotoObj,1));
}
}
break;
case aJson_Int:
case aJson_String:
return setCurrentInput(gotoObj);
break;
}
return false;
}
// TODO Polling via timed interrupt with CHECK_INTERRUPT cause
bool Input::changeState(uint8_t newState, short cause)
aJsonObject * Input::getCurrentInput()
{
if (!inputObj) return NULL;
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
if (act && (act->type == aJson_Array || act->type == aJson_Object) && act->valuestring) return (aJsonObject * ) act->valuestring;
return inputObj;
}
bool Input::setCurrentInput(aJsonObject * obj)
{
if (!obj) return false;
switch (obj->type)
{
case aJson_Int:
debugSerial<<F("Activate in ")<<pin <<" to "<< obj->valueint <<endl;
return setCurrentInput(obj->valueint);
break;
case aJson_String:
debugSerial<<F("Activate in ")<<pin <<" to "<< obj->valuestring <<endl;
return setCurrentInput(obj->valuestring);
}
return false;
}
bool Input::setCurrentInput(int n)
{
if (!inputObj) return false;
aJsonObject * curInput = NULL;
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
if (act && (act->type == aJson_Array || act->type ==aJson_Object))
{
if (n)
curInput = aJson.getArrayItem(act,n-1);
else curInput = inputObj;
act->valuestring = (char *) curInput;
return true;
}
return false;
}
bool Input::setCurrentInput(char * name)
{
if (!inputObj) return false;
aJsonObject * curInput = NULL;
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
if (act && act->type == aJson_Object)
{
if (name && *name)
curInput = aJson.getObjectItem(act,name);
else curInput = inputObj;
act->valuestring = (char *) curInput;
return true;
}
return false;
}
bool Input::
changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer)
{
if (!inputObj || !store) return false;
if (newState == IS_REQSTATE)
if (store->delayedState && cause != CHECK_INTERRUPT)
if (store->delayedState && (cause != CHECK_INTERRUPT))
{
// Requested delayed change State and safe moment
newState=store->reqState; //Retrieve requested state
debugSerial<<F("Pended: #")<<pin<<F(" ")<<store->state<<F("->") <<newState<<endl;
contactState = store->lastValue;
if (store->state == newState)
{
store->delayedState = false;
@@ -550,37 +715,37 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
switch (store->state)
{
case IS_RELEASED: //click
cmd = aJson.getObjectItem(inputObj, "click");
cmd = aJson.getObjectItem(currentInputObject, "click");
toggle=store->toggle1;
break;
case IS_RELEASED2: //doubleclick
cmd = aJson.getObjectItem(inputObj, "dclick");
cmd = aJson.getObjectItem(currentInputObject, "dclick");
toggle=store->toggle2;
break;
case IS_PRESSED3: //tripple click
cmd = aJson.getObjectItem(inputObj, "tclick");
cmd = aJson.getObjectItem(currentInputObject, "tclick");
toggle=store->toggle3;
break;
case IS_WAITPRESS: //do nothing
break;
default: //rcmd
cmd = aJson.getObjectItem(inputObj, "rcmd");
cmd = aJson.getObjectItem(currentInputObject, "rcmd");
;
}
break;
case IS_PRESSED: //scmd
cmd = aJson.getObjectItem(inputObj, "scmd");
cmd = aJson.getObjectItem(currentInputObject, "scmd");
toggle=store->toggle1;
store->toggle1 = !store->toggle1;
if (!cmd) defCmd.Cmd(CMD_ON);
break;
case IS_PRESSED2: //scmd2
cmd = aJson.getObjectItem(inputObj, "scmd2");
cmd = aJson.getObjectItem(currentInputObject, "scmd2");
toggle=store->toggle2;
store->toggle2 = !store->toggle2;
break;
case IS_PRESSED3: //scmd3
cmd = aJson.getObjectItem(inputObj, "scmd3");
cmd = aJson.getObjectItem(currentInputObject, "scmd3");
toggle=store->toggle3;
store->toggle3 = !store->toggle3;
break;
@@ -588,46 +753,69 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
case IS_RELEASED: //rcmd
case IS_WAITPRESS:
case IS_RELEASED2:
cmd = aJson.getObjectItem(inputObj, "rcmd");
cmd = aJson.getObjectItem(currentInputObject, "rcmd");
if (!cmd) defCmd.Cmd(CMD_OFF);
// toggle=state->toggle1;
break;
case IS_LONG: //lcmd
cmd = aJson.getObjectItem(inputObj, "lcmd");
cmd = aJson.getObjectItem(currentInputObject, "lcmd");
toggle=store->toggle1;
break;
case IS_REPEAT: //rpcmd
cmd = aJson.getObjectItem(inputObj, "rpcmd");
cmd = aJson.getObjectItem(currentInputObject, "rpcmd");
toggle=store->toggle1;
break;
case IS_LONG2: //lcmd2
cmd = aJson.getObjectItem(inputObj, "lcmd2");
cmd = aJson.getObjectItem(currentInputObject, "lcmd2");
toggle=store->toggle2;
break;
case IS_REPEAT2: //rpcmd2
cmd = aJson.getObjectItem(inputObj, "rpcmd2");
cmd = aJson.getObjectItem(currentInputObject, "rpcmd2");
toggle=store->toggle2;
break;
case IS_LONG3: //lcmd3
cmd = aJson.getObjectItem(inputObj, "lcmd3");
cmd = aJson.getObjectItem(currentInputObject, "lcmd3");
toggle=store->toggle3;
break;
case IS_REPEAT3: //rpcmd3
cmd = aJson.getObjectItem(inputObj, "rpcmd3");
cmd = aJson.getObjectItem(currentInputObject, "rpcmd3");
toggle=store->toggle3;
break;
case IS_NOP:
if (!calledOnTimer) break;
if (contactState)
cmd = aJson.getObjectItem(currentInputObject, "scmd");
else cmd = aJson.getObjectItem(currentInputObject, "rcmd");
break;
}
aJsonObject *defaultItem = aJson.getObjectItem(inputObj, "item");
aJsonObject *defaultEmit = aJson.getObjectItem(inputObj, "emit");
if (!calledOnTimer || newState == IS_NOP)
{
if (cause != CHECK_INTERRUPT)
{
onContactChanged(contactState);
store->delayedState=false;
}
else
{
store->delayedState=true;
store->lastValue = contactState;
store->reqState=newState;
}
}
if ((newState == IS_NOP) && !calledOnTimer) return true;
aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item");
aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit");
aJsonObject *defaultCan = aJson.getObjectItem(currentInputObject, "can");
if (!defaultEmit && !defaultItem) defCmd.Cmd(CMD_VOID);
if (!cmd && !defCmd.isCommand())
{
store->state=newState;
if (newState !=IS_NOP) store->state=newState;
store->delayedState=false;
return true; //nothing to do
}
@@ -635,15 +823,16 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
if (cause != CHECK_INTERRUPT)
{
store->state=newState;
if (newState !=IS_NOP) store->state=newState;
store->delayedState=false;
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit);
checkInstructions(cmd);
executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit,defaultCan);
return true;
}
else
{
//Postpone actual execution
if (newState != store->state)
if ((newState != store->state) && (newState !=IS_NOP))
{
store->reqState=newState;
store->delayedState=true;
@@ -654,13 +843,22 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<<F("#")<<pin<<
}
static volatile uint8_t contactPollBusy = 0;
#ifdef ROTARYENCODER
void Input::contactPoll(short cause, RotaryEncoder * re)
#else
void Input::contactPoll(short cause)
#endif
{
bool currentInputState;
void Input::contactPoll(short cause) {
boolean currentInputState;
if (!store /*|| contactPollBusy*/) return;
contactPollBusy++;
if ((inType == IN_ULTRASONIC) && (cause!=CHECK_ULTRASONIC)) return;
changeState(IS_REQSTATE,cause); //Check for postponed states transitions
contactPollBusy++;
aJsonObject * currentInputObject = getCurrentInput();
changeState(IS_REQSTATE,cause,currentInputObject,false); //Check for postponed states transitions
uint8_t inputOnLevel;
@@ -674,29 +872,31 @@ if (inType & IN_I2C)
currentInputState = (inCache.I2CReadBit(IN_I2C,0,pin) == inputOnLevel);
else
#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)
currentInputState = true;
else currentInputState = false;
}
else currentInputState = (digitalRead(pin) == inputOnLevel);
if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
if (cause != CHECK_INTERRUPT)
{
switch (store->state) //Timer based transitions
{
case IS_PRESSED:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
{
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(inputObj, "rpcmd")) changeState(IS_WAITRELEASE, cause);
else changeState(IS_LONG, cause);
if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
else changeState(IS_LONG, cause,currentInputObject,currentInputState,true);
}
break;
case IS_LONG:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
{
changeState(IS_REPEAT, cause);
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -704,7 +904,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_REPEAT:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
{
changeState(IS_REPEAT, cause);
changeState(IS_REPEAT, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -712,15 +912,15 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_PRESSED2:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
{
if (!aJson.getObjectItem(inputObj, "lcmd2") && !aJson.getObjectItem(inputObj, "rpcmd2")) changeState(IS_WAITRELEASE, cause);
else changeState(IS_LONG2, cause);
if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true);
else changeState(IS_LONG2, cause,currentInputObject,currentInputState,true);
}
break;
case IS_LONG2:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
{
changeState(IS_REPEAT2, cause);
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -728,7 +928,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_REPEAT2:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
{
changeState(IS_REPEAT2, cause);
changeState(IS_REPEAT2, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -736,19 +936,19 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_PRESSED3:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF))
{
if (!aJson.getObjectItem(inputObj, "lcmd3") && !aJson.getObjectItem(inputObj, "rpcmd3")) //No longpress handlers
if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers
{
if (aJson.getObjectItem(inputObj, "scmd3")) changeState(IS_WAITRELEASE, cause); //was used
else changeState(IS_PRESSED2, cause); // completely empty trippleClick section - fallback to first click handler
if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState,true); //was used
else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState,true); // completely empty trippleClick section - fallback to first click handler
}
else changeState(IS_LONG3, cause);
else changeState(IS_LONG3, cause,currentInputObject,currentInputState,true);
}
break;
case IS_LONG3:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF))
{
changeState(IS_REPEAT3, cause);
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -756,7 +956,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_REPEAT3:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF))
{
changeState(IS_REPEAT3, cause);
changeState(IS_REPEAT3, cause,currentInputObject,currentInputState,true);
store->timestamp16 = millis() & 0xFFFF;
}
break;
@@ -766,11 +966,28 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_WAITPRESS:
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause);
if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState,true);
break;
} //switch
#ifdef ROTARYENCODER
if (re)
{
aJsonObject * bufferItem;
switch (re->getDirection())
{
case RotaryEncoder::Direction::CLOCKWISE:
if (bufferItem=aJson.getObjectItem(currentInputObject, "+-")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
if (bufferItem=aJson.getObjectItem(currentInputObject, "+")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
break;
case RotaryEncoder::Direction::COUNTERCLOCKWISE:
if (bufferItem=aJson.getObjectItem(currentInputObject, "+-")) {checkInstructions(bufferItem);executeCommand(bufferItem,1);};
if (bufferItem=aJson.getObjectItem(currentInputObject, "-")) {checkInstructions(bufferItem);executeCommand(bufferItem,0);};
}
if (currentInputState != store->lastValue) // value changed
}
#endif
} //if not INTERRUPT
if ((currentInputState != store->lastValue) || // value changed
(isTimeOver(store->timestamp16,millis() & 0xFFFF,T_REPEAT,0xFFFF) && getIntFromJson(currentInputObject,"repeat")))
{
if (store->bounce) store->bounce = store->bounce - 1;
else //confirmed change
@@ -788,7 +1005,7 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
} else */
{
// onContactChanged(currentInputState); //Legacy input - to remove later
////// onContactChanged(currentInputState); //Legacy input - to remove later // wrong place - INTERRUPTS
bool res = true;
if (currentInputState) //Button pressed state transitions
@@ -796,52 +1013,55 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
switch (store->state)
{
case IS_IDLE:
res = changeState(IS_PRESSED, cause);
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
break;
case IS_RELEASED:
case IS_WAITPRESS:
if ( //No future
!aJson.getObjectItem(inputObj, "scmd2") &&
!aJson.getObjectItem(inputObj, "lcmd2") &&
!aJson.getObjectItem(inputObj, "rpcmd2") &&
!aJson.getObjectItem(inputObj, "dclick")
!aJson.getObjectItem(currentInputObject, "scmd2") &&
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
!aJson.getObjectItem(currentInputObject, "dclick")
)
res = changeState(IS_PRESSED, cause);
res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState);
else res = changeState(IS_PRESSED2, cause);
else res = changeState(IS_PRESSED2, cause,currentInputObject,currentInputState);
break;
case IS_RELEASED2:
res = changeState(IS_PRESSED3, cause);
res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState);
break;
default:
res = changeState(IS_NOP, cause,currentInputObject,currentInputState,(currentInputState == store->lastValue));
}
else
switch (store->state) //Button released state transitions
{
case IS_PRESSED:
res = changeState(IS_RELEASED, cause);
res = changeState(IS_RELEASED, cause,currentInputObject,currentInputState);
break;
case IS_LONG:
case IS_REPEAT:
case IS_WAITRELEASE:
res = changeState(IS_WAITPRESS, cause);
res = changeState(IS_WAITPRESS, cause,currentInputObject,currentInputState);
break;
case IS_PRESSED2:
if ( //No future
!aJson.getObjectItem(inputObj, "scmd2") &&
!aJson.getObjectItem(inputObj, "lcmd2") &&
!aJson.getObjectItem(inputObj, "rpcmd2") &&
!aJson.getObjectItem(inputObj, "dclick")
) res = changeState(IS_IDLE, cause);
else res = changeState(IS_RELEASED2, cause);
!aJson.getObjectItem(currentInputObject, "scmd2") &&
!aJson.getObjectItem(currentInputObject, "lcmd2") &&
!aJson.getObjectItem(currentInputObject, "rpcmd2") &&
!aJson.getObjectItem(currentInputObject, "dclick")
) res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
else res = changeState(IS_RELEASED2, cause,currentInputObject,currentInputState);
break;
case IS_LONG2:
@@ -849,8 +1069,10 @@ if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions
case IS_LONG3:
case IS_REPEAT3:
case IS_PRESSED3:
res = changeState(IS_IDLE, cause);
res = changeState(IS_IDLE, cause,currentInputObject,currentInputState);
break;
default:
res = changeState(IS_NOP, cause,currentInputObject,currentInputState, (currentInputState == store->lastValue));
}
if (res) { //State changed or postponed
// store->logicState = currentInputState;
@@ -886,7 +1108,7 @@ void Input::analogPoll(short cause) {
pinMode(pin, inputPinMode);
*/
inputVal = inCache.analogReadCached(pin);
inputVal = inCache.analogReadCached(pin,pin2,inType);
// Mapping
if (inputMap && inputMap->type == aJson_Array)
{
@@ -950,7 +1172,8 @@ void Input::onContactChanged(int newValue) {
aJsonObject *item = aJson.getObjectItem(inputObj, "item");
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 *rcmd = aJson.getObjectItem(inputObj, "rcmd");
debugSerial << F("LEGACY IN:") << (pin) << F("=") << newValue << endl;
@@ -965,20 +1188,23 @@ void Input::onContactChanged(int newValue) {
} else
#endif
{
#if not defined (NOIP)
char addrstr[MQTT_TOPIC_LENGTH];
strncpy(addrstr,emit->valuestring,sizeof(addrstr));
if (mqttClient.connected() && !ethernetIdleCount)
{
if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring);
if (newValue) { //send set command
if (!scmd || scmd->type != aJson_String) mqttClient.publish(addrstr, "ON", true);
else if (strlen(scmd->valuestring))
mqttClient.publish(addrstr, scmd->valuestring, true);
if (!scmd) {mqttClient.publish(addrstr, "ON", true); debugSerial<<F("Emit:")<<addrstr<< F("->") << "ON"<<endl;}
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
{mqttClient.publish(addrstr, scmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << scmd->valuestring<<endl;}
} else { //send reset command
if (!rcmd || rcmd->type != aJson_String) mqttClient.publish(addrstr, "OFF", true);
else if (strlen(rcmd->valuestring))mqttClient.publish(addrstr, rcmd->valuestring, true);
if (!rcmd) {mqttClient.publish(addrstr, "OFF", true);debugSerial<<F("Emit:")<<addrstr<< F("->") << "OFF"<<endl;}
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring)) {mqttClient.publish(addrstr, rcmd->valuestring, true);debugSerial<<F("Emit:")<<addrstr<< F("->") << rcmd->valuestring<<endl;}
}
}
#endif //NOIP
}
} // emit
if (item && item->type == aJson_String) {
@@ -986,16 +1212,32 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri
Item it(item->valuestring);
if (it.isValid()) {
if (newValue) { //send set command
if (!scmd || scmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
else if (strlen(scmd->valuestring))
if (!scmd ) it.Ctrl(itemCmd(ST_VOID,CMD_ON));
else if ((scmd->type == aJson_String) && strlen(scmd->valuestring))
it.Ctrl(scmd->valuestring);
} else { //send reset command
if (!rcmd || rcmd->type != aJson_String) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
else if (strlen(rcmd->valuestring))
if (!rcmd ) it.Ctrl(itemCmd(ST_VOID,CMD_OFF));
else if ((rcmd->type == aJson_String) && strlen(rcmd->valuestring))
it.Ctrl(rcmd->valuestring);
}
}
}
#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
}
@@ -1004,13 +1246,13 @@ void Input::onAnalogChanged(itemCmd newValue) {
// New tyle unified activities
aJsonObject *act = aJson.getObjectItem(inputObj, "act");
//checkInstructions(act);
executeCommand(act,-1,newValue);
// Legacy
aJsonObject *item = aJson.getObjectItem(inputObj, "item");
aJsonObject *emit = aJson.getObjectItem(inputObj, "emit");
#if not defined (NOIP)
if (emit && emit->type == aJson_String) {
//#ifdef WITH_DOMOTICZ
@@ -1028,11 +1270,18 @@ void Input::onAnalogChanged(itemCmd newValue) {
if (mqttClient.connected() && !ethernetIdleCount)
mqttClient.publish(addrstr, strVal, true);
}
#endif //NOIP
if (item && item->type == aJson_String) {
Item it(item->valuestring);
if (it.isValid()) it.Ctrl(newValue);
}
#ifdef CANDRV
aJsonObject *can = aJson.getObjectItem(inputObj, "can");
if (can) LHCAN.sendCommand(can, newValue);
#endif
}
@@ -1072,10 +1321,21 @@ readCache::readCache()
{
addr=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;
addr = _pin;
type = IN_ANALOG;

View File

@@ -1,4 +1,4 @@
/* Copyright © 2017-2018 Andrey Klimov. All rights reserved.
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -21,6 +21,9 @@ e-mail anklimov@gmail.com
#include <aJSON.h>
#include "modules/in_ccs811_hdc1080.h"
#include "itemCmd.h"
#ifdef ROTARYENCODER
#include "RotaryEncoder.h"
#endif
#define IN_ACTIVE_HIGH 2 // High level = PUSHED/ CLOSED/ ON othervise :Low Level. Use INPUT mode instead of INPUT_PULLUP for digital pin
#define IN_ANALOG 64 // Analog input
@@ -33,6 +36,7 @@ e-mail anklimov@gmail.com
#define IN_DHT22 4
#define IN_CCS811 5
#define IN_HDC1080 6
#define IN_ULTRASONIC 7
#define IN_COUNTER 8
#define IN_UPTIME 16
@@ -52,6 +56,7 @@ e-mail anklimov@gmail.com
#define IS_REPEAT3 12u
#define IS_WAITRELEASE 13u
#define IS_REQSTATE 0xFF
#define IS_NOP 0xF
@@ -62,12 +67,14 @@ e-mail anklimov@gmail.com
#define CHECK_SENSOR 1
#define CHECK_INPUT 2
#define CHECK_INTERRUPT 3
#define CHECK_ULTRASONIC 4
#define T_LONG 1000
#define T_IDLE 600
#define T_RPT 300
#define T_RPT_PULSE 150
#define T_REPEAT 30000
@@ -105,7 +112,7 @@ extern aJsonObject *inputs;
typedef union {
long int aslong;
uint32_t aslong;
uint32_t timestamp;
// Analog input structure
struct {
@@ -134,6 +141,7 @@ public:
aJsonObject *inputObj;
uint8_t inType;
uint8_t pin;
uint8_t pin2;
inStore *store;
Input(aJsonObject *obj, aJsonObject * configObj = NULL);
@@ -146,6 +154,7 @@ public:
int Poll(short cause);
void setup();
void stop();
static void inline onCounterChanged(int i);
static void onCounterChanged0();
@@ -160,7 +169,12 @@ public:
protected:
void Parse(aJsonObject * configObj = NULL);
#ifdef ROTARYENCODER
void contactPoll(short cause, RotaryEncoder * re = NULL);
#else
void contactPoll(short cause);
#endif
void analogPoll(short cause);
void dht22Poll();
@@ -179,7 +193,16 @@ protected:
bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...);
char* getIdxField();
bool changeState(uint8_t newState, short cause);
bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState, bool calledOnTimer = false);
void setupRotaryEncoder();
aJsonObject * getCurrentInput();
bool setCurrentInput(aJsonObject * obj);
bool setCurrentInput(int n);
bool setCurrentInput(char * name);
bool checkInstructions(aJsonObject * obj);
//bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL);
};
@@ -188,11 +211,12 @@ protected:
class readCache {
public:
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);
#ifdef MCP23017
uint8_t I2CReadBit(uint8_t type, uint8_t addr, uint8_t pin);
#endif
void invalidateInputCache();
protected:
uint8_t addr;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* Copyright © 2017-2020 Andrey Klimov. All rights reserved.
/* Copyright © 2017-2025 Andrey Klimov. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@ e-mail anklimov@gmail.com
#include "abstractout.h"
#include "itemCmd.h"
#define S_NOTFOUND 0
#define S_CMD 1
#define S_SET 2
@@ -67,12 +68,17 @@ const suffixstr suffix_P[] PROGMEM =
#define CH_COUNTER 20
#define CH_HUMIDIFIER 21
#define CH_MERCURY 22
#define CH_MAX 22
#define POLLING_SLOW 1
#define POLLING_FAST 2
#define POLLING_INT 3
#define POLLING_1S 4
//CTRL Execution flags
#define CTRL_DISABLE_RECURSION 1
#define CTRL_DISABLE_NON_GRP 2
#define CTRL_SCHEDULED_CALL_RECURSION (CTRL_DISABLE_RECURSION | CTRL_DISABLE_NON_GRP)
#define I_TYPE 0 //Type of item
#define I_ARG 1 //Chanel-type depended argument or array of arguments (pin, address etc)
@@ -98,25 +104,27 @@ extern aJsonObject *items;
extern short thermoSetCurTemp(char *name, float t);
int txt2cmd (char * payload);
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false);
int txt2subItem(char *payload);
class Item
{
public:
aJsonObject *itemArr, *itemArg,*itemVal,*itemExt;
aJsonObject *rootItems, *itemArr, *itemArg,*itemVal,*itemExt;
uint8_t itemType;
abstractOut * driver;
Item(char * name);
Item(aJsonObject * obj);
Item(char * name, aJsonObject *_items = items);
Item(aJsonObject * obj, aJsonObject *_items = items);
Item(uint16_t num, uint8_t subItem, aJsonObject *_items = items);
~Item();
boolean isValid ();
boolean Setup();
void Stop();
//int Ctrl(short cmd, short n=0, int * Parameters=NULL, int suffixCode=0, char* subItem=NULL);
int Ctrl(itemCmd cmd, char* subItem=NULL, bool allowRecursion = true, bool authorized=false);
int Ctrl(char * payload, char * subItem=NULL);
int Ctrl(itemCmd cmd, char* subItem=NULL, uint8_t flags = 0, bool authorized=false);
int Ctrl(char * payload, char * subItem=NULL, int remoteID = 0);
int remoteCtrl(itemCmd cmd, int remoteID, char* subItem=NULL, char * authToken=NULL);
int getArg(short n=0);
float getFloatArg(short n=0);
short getArgCount();
@@ -136,18 +144,21 @@ class Item
void setFloatVal(float par);
void setSubtype(uint8_t par);
int Poll(int cause);
int SendStatus(int sendFlags);
int SendStatusImmediate(itemCmd st, int sendFlags, char * subItem=NULL);
int SendStatus(long sendFlags, char * subItem=NULL);
int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL, bool tetain = true);
int isActive();
int getChanType();
inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));};
inline int Off(){return Ctrl(itemCmd(ST_VOID,CMD_OFF));};
inline int Toggle(){return Ctrl(itemCmd(ST_VOID,CMD_TOGGLE));};
int scheduleCommand(itemCmd cmd, bool authorized);
int scheduleOppositeCommand(itemCmd cmd,bool isActiveNow,bool authorized);
int scheduleOppositeCommand(itemCmd cmd,short isActiveNow,bool authorized);
int isScheduled();
char * getSubItemStrById(uint8_t subItem);
uint8_t getSubitemId(char * subItem);
protected:
bool digGroup (aJsonObject *itemArr, itemCmd *cmd = NULL, char* subItem = NULL, bool authorized = false, uint8_t ctrlFlags = 0);
long int limitSetValue();
int VacomSetFan (itemCmd st);
int VacomSetHeat(itemCmd st);
@@ -164,6 +175,18 @@ class Item
int defaultSuffixCode;
};
class driverFactory {
public:
driverFactory(){memset(drivers,0,sizeof(drivers));};
Item * getItem(Item * item);
abstractOut * getDriver(Item * item);
abstractOut * findDriver(Item * item);
void freeDriver(Item * item);
abstractOut * newDriver(uint8_t itemType);
private:
abstractOut * drivers[CH_MAX+1];
};
typedef union
{
struct

View File

@@ -94,6 +94,86 @@ itemCmd::itemCmd(Item *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)
{
@@ -349,6 +429,23 @@ bool itemCmd::incrementS(long int dif)
}
bool itemCmd::incrementTemp(long int dif)
{int par=param.colorTemp;
switch (cmd.itemArgType)
{
case ST_HSV255:
par+=dif/TENS_BASE;
if (par>100) par=100;
if (par<1) par=1;
break;
default: return false;
}
param.colorTemp=par;
return true;
}
itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
{
@@ -596,7 +693,7 @@ itemCmd itemCmd::assignFrom(itemCmd from, short chanType)
{
long coldPercent = map (colorT,0,100,100,30);
long hotPercent = map (colorT,0,100,30,100);
int rgbvLevel;
int rgbvLevel = 0;
if (rgbSaturation < 128) { // Using white
param.w=map((127 - rgbSaturation) * rgbValue *hotPercent, 0, 127*255*100, 0, 255);
@@ -950,7 +1047,7 @@ itemCmd itemCmd::Int(int32_t i)
return *this;
}
itemCmd itemCmd::Int(uint32_t i)
itemCmd itemCmd::uInt(uint32_t i)
{
cmd.itemArgType=ST_UINT32;
param.asUint32=i;
@@ -1083,7 +1180,7 @@ bool itemCmd::loadItem(Item * item, uint16_t optionsFlag)
{
case aJson_Int:
Int((int32_t)item->itemVal->valueint);
Int(item->itemVal->valueint);
//debugSerial<<F("Loaded Int:");
//debugOut();
return true;
@@ -1131,7 +1228,7 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
case CMD_ENABLE:
item->clearFlag(FLAG_DISABLED);
item->clearFlag(FLAG_FREEZED);
//? item->clearFlag(FLAG_FREEZED); //?
break;
case CMD_FREEZE:
item->setFlag(FLAG_FREEZED);
@@ -1151,6 +1248,7 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
break;
default:
item->setCmd(cmd.cmdCode);
}
if (optionsFlag & FLAG_PARAMETERS)
switch (cmd.itemArgType)
@@ -1171,8 +1269,8 @@ bool itemCmd::saveItem(Item * item, uint16_t optionsFlag)
item->setVal(param.asInt32);
item->setSubtype(cmd.itemArgType);
}
debugSerial<<F("Saved:");
debugOut();
//debugSerial<<F("Saved:");
//debugOut();
return true;
}
return false;
@@ -1196,7 +1294,13 @@ return false;
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);
if (type>=0)
@@ -1206,7 +1310,9 @@ return false;
verb->type=aJson_Int;
return verb->valueint;
}
} else if (verb && verb->type == aJson_Int) return verb->valueint;
}
break;
}
return -1;
}
@@ -1222,7 +1328,7 @@ return false;
{
case aJson_Array:
{
debugSerial<<"Array mapping"<<endl;
traceSerial<<"Array mapping"<<endl;
aJsonObject *i = cmdMapping->child;
//if first array element is not array - this is default mapping value
if (i && i->type==aJson_Int)
@@ -1262,13 +1368,13 @@ return false;
return itemCmd().Int((uint32_t)2);
*/
case CMD_OFF:
return itemCmd().Int((uint32_t)0);
return itemCmd().Int(0);
case CMD_LOW:
return itemCmd().Int((uint32_t)20);
return itemCmd().Int(20);
case CMD_MED:
return itemCmd().Int((uint32_t)128);
return itemCmd().Int(128);
case CMD_HIGH:
return itemCmd().Int((uint32_t)255);
return itemCmd().Int(255);
default:
return *this;
@@ -1278,17 +1384,40 @@ return false;
if (matchedCmd && matchedCmd->type != aJson_NULL)
{
return itemCmd().Int((uint32_t)matchedCmd->valueint);
traceSerial<<F("MAP: cmd mapped to ")<<matchedCmd->valueint<<endl;
return itemCmd().Int(matchedCmd->valueint);
}
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
{ //ПРЯМОЕ
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,4);
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,6);
//if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0); было если меньше левой границы то ноль. Неперь для такого поведения надо пятым элементом явно поставить ноль
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint)
{
if (getInt()<aJson.getArrayItem(valMapping,0)->valueint) return itemCmd().Int((uint32_t) 0);
return itemCmd().Int((uint32_t)
map(getInt(),
traceSerial<<F("MAP: value ")<<getInt()<<F(" is below left bound ")<<aJson.getArrayItem(valMapping,0)->valueint<<endl;
if (leftBoundObj && leftBoundObj->type == aJson_Int )
return itemCmd().Int(leftBoundObj->valueint);
else return itemCmd(ST_VOID,CMD_VOID);
}
if (getInt()>aJson.getArrayItem(valMapping,1)->valueint)
{
traceSerial<<F("MAP: value above right bound ")<<endl;
if (rightBoundObj && rightBoundObj->type == aJson_Int )
return itemCmd().Int(rightBoundObj->valueint);
else return itemCmd(ST_VOID,CMD_VOID);
}
long res = map(getInt(),
aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint,
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint));
aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint);
traceSerial<<F("MAP: val mapped to ")<<res<<endl;
return itemCmd().Int(res);
}
else if (valMapping && valMapping->type == aJson_NULL) return itemCmd(ST_VOID,CMD_VOID);
return *this;
@@ -1356,16 +1485,40 @@ if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArray
if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint);
aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val");
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4)
if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) >= 4)
{
//ОБРАТНОЕ
//"val":[0-вход_мин, 1-вход_макс, 2-выход_мин, 3-выход_макс, 4-вход<мин_прямое, 5-вых<мин_обратное, 6-вход>макс_прямое, 7-вых>макс_обратное]
int a = aJson.getArrayItem(valMapping,0)->valueint;
int b = aJson.getArrayItem(valMapping,1)->valueint;
int c = aJson.getArrayItem(valMapping,2)->valueint;
int d = aJson.getArrayItem(valMapping,3)->valueint;
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
aJsonObject *leftBoundObj = aJson.getArrayItem(valMapping,5);
aJsonObject *rightBoundObj = aJson.getArrayItem(valMapping,7);
// Dev to unified
//было если меньше левой границы то ноль. Неперь для такого поведения надо 7m элементом явно поставить ноль
//if (getInt()<aJson.getArrayItem(valMapping,2)->valueint) return itemCmd().Int((uint32_t) 0);
if (getInt()<aJson.getArrayItem(valMapping,2)->valueint)
{
if (leftBoundObj && leftBoundObj->type == aJson_Int )
return itemCmd().Int(leftBoundObj->valueint);
else return itemCmd(ST_VOID,CMD_VOID);
}
if (getInt()>aJson.getArrayItem(valMapping,3)->valueint)
{
if (rightBoundObj && rightBoundObj->type == aJson_Int )
return itemCmd().Int(rightBoundObj->valueint);
else return itemCmd(ST_VOID,CMD_VOID);
}
int diff = ((b-a)/(d-c))/2;
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
//return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255));
return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,b));
//return itemCmd().Int((uint32_t) map(getInt(),c,d,a,b)+diff);
}
if (valMapping && valMapping->type == aJson_NULL) return itemCmd();
return *this;
@@ -1378,7 +1531,7 @@ char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100
if (!Buffer || !bufLen) return NULL;
*Buffer=0;
char * argPtr=Buffer;
if (isCommand() && (sendFlags & FLAG_COMMAND))
if (isCommand() && (sendFlags & FLAG_COMMAND) && cmd.cmdCode<commandsNum)
{
int len;
strncpy_P(Buffer, commands_P[cmd.cmdCode], bufLen);

View File

@@ -21,15 +21,15 @@ e-mail anklimov@gmail.com
#include "Arduino.h"
#include "aJSON.h"
typedef char cmdstr[9];
typedef char cmdstr[10];
const cmdstr commands_P[] PROGMEM =
{
"","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE",
"ENABLE","DISABLE","UNFREEZE","FREEZE",
"AUTO","FAN_ONLY",
"HIGH","MEDIUM","LOW",
"HEAT","COOL","DRY","STOP","RGB","HSV"
"HIGH","MEDIUM","LOW","HEAT_COOL",
"HEAT","COOL","DRY","RGB","HSV"
};
#define commandsNum sizeof(commands_P)/sizeof(cmdstr)
@@ -87,10 +87,10 @@ const ch_type ch_type_P[] PROGMEM =
#define CMD_MED 0x11 /// AC/Vent fan level MEDIUM
#define CMD_LOW 0x12 /// AC/Vent fan level LOW
#define CMD_HEAT 0x13 /// Thermostat/AC set to HEATing mode
#define CMD_COOL 0x14 /// Thermostat/AC set to COOLing mode
#define CMD_DRY 0x15 /// AC set to Dry mode
#define CMD_STOP 0x16 /// stop dimming (for further use)
#define CMD_HEATCOOL 0x13 ///
#define CMD_HEAT 0x14 /// Thermostat/AC set to HEATing mode
#define CMD_COOL 0x15 /// Thermostat/AC set to COOLing mode
#define CMD_DRY 0x16 /// AC set to Dry mode
#define CMD_RGB 0x17
#define CMD_HSV 0x18
@@ -104,22 +104,41 @@ const ch_type ch_type_P[] PROGMEM =
#define CMD_JSON -2
//FLAGS
#define FLAG_SEND_IMMEDIATE 0x1UL
#define FLAG_COMMAND 0x100UL
#define FLAG_PARAMETERS 0x200UL
#define FLAG_FLAGS 0x400UL
#define FLAG_SEND_RETRY 0x800UL
#define FLAG_SEND_DEFFERED 0x1000UL
#define FLAG_SEND_DELAYED 0x2000UL
#define FLAG_ACTION_NEEDED 0x4000UL
#define FLAG_ACTION_IN_PROCESS 0x8000UL
#define FLAG_DISABLED 0x10000UL
#define FLAG_FREEZED 0x20000UL
//#define FLAG_COMMAND 0x100UL
//#define FLAG_PARAMETERS 0x200UL
//#define FLAG_FLAGS 0x400UL
//#define FLAG_SEND_RETRY 0x800UL
//#define FLAG_SEND_DEFFERED 0x1000UL
//#define FLAG_SEND_DELAYED 0x2000UL
//#define FLAG_ACTION_NEEDED 0x4000UL
//#define FLAG_ACTION_IN_PROCESS 0x8000UL
//#define FLAG_DISABLED 0x10000UL
//#define FLAG_FREEZED 0x20000UL
//#define FLAG_HALTED 0x40000UL
//#define FLAG_XON 0x80000UL
#define FLAG_DISABLED 0x100UL
#define FLAG_LOCKED_CMD 0x200UL
#define FLAG_LOCKED_SET 0x400UL
#define FLAG_FREEZED 0x600UL
#define FLAG_SEND_DEFFERED 0x800UL
#define FLAG_COMMAND 0x1000UL
#define FLAG_PARAMETERS 0x2000UL
#define FLAG_FLAGS 0x4000UL
#define FLAG_SEND_RETRY 0x8000UL
#define FLAG_ACTION_NEEDED 0x10000UL
#define FLAG_ACTION_IN_PROCESS 0x20000UL
#define FLAG_HALTED 0x40000UL
#define FLAG_XON 0x80000UL
#define FLAG_SEND_DELAYED 0x100000UL
#define FLAG_SEND_IMMEDIATE 0x1UL
#define FLAG_NOT_SEND_CAN 0x2UL
int txt2cmd (char * payload);
@@ -157,10 +176,9 @@ typedef union
struct
{
uint8_t cmdCode;
uint8_t suffixCode:4;
uint8_t itemArgType:4;
uint8_t cmdEffect; //Reserve
uint8_t cmdEffect:4; //Reserve
uint8_t suffixCode;
uint8_t cmdParam; //Reserve
};
} itemCmdStore;
@@ -204,6 +222,7 @@ public:
itemCmd(uint8_t _type=ST_VOID, uint8_t _code=CMD_VOID);
itemCmd(float val);
itemCmd(Item *item);
itemCmd(char *cmd);
itemCmd assignFrom(itemCmd from, short chanType=-1);
@@ -212,7 +231,7 @@ public:
bool saveItem(Item * item, uint16_t optionsFlag=FLAG_PARAMETERS);
itemCmd Int(int32_t i);
itemCmd Int(uint32_t i);
itemCmd uInt(uint32_t i);
itemCmd Float(float f);
itemCmd Tens(int32_t i);
itemCmd Tens_raw(int32_t i);
@@ -242,6 +261,7 @@ public:
bool incrementPercents(long int, long int limit);
bool incrementH(long int);
bool incrementS(long int);
bool incrementTemp(long int dif);
long int getInt();
long int getTens();

File diff suppressed because it is too large Load Diff

View File

@@ -8,13 +8,17 @@
#if defined(__SAM3X8E__)
#include <watchdog.h>
#if not defined (NOIP)
#include <ArduinoHttpClient.h>
#endif
//#include "TimerInterrupt_Generic.h"
#endif
#if defined(ARDUINO_ARCH_AVR)
#if not defined (NOIP)
#include "HTTPClient.h"
//#include <ArduinoHttpClient.h>
#endif
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#endif
@@ -35,7 +39,7 @@
//#define Ethernet WiFi
#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 "SPIFFS.h"
//#include <EEPROM.h>
@@ -58,7 +62,7 @@
#include <ArduinoHttpClient.h>
#endif
#ifdef ARDUINO_ARCH_STM32
#if defined (ARDUINO_ARCH_STM32) and not defined (NOIP)
#include "HttpClient.h"
//#include "UIPEthernet.h"
//#include <NRFFlashStorage.h>
@@ -156,7 +160,8 @@ extern Streamlog errorSerial;
#include <ESP8266mDNS.h>
#endif
#define Ethernet WiFi
#else //Wired connection
#else
#if not defined (NOIP) //Wired connection
#ifdef Wiz5500
#include <Ethernet2.h>
#else
@@ -167,6 +172,7 @@ extern Streamlog errorSerial;
#endif
#endif
#endif
#endif
#ifdef _artnet
@@ -190,7 +196,9 @@ extern Streamlog errorSerial;
#include "Arduino.h"
#include "utils.h"
#include "textconst.h"
#if not defined (NOIP)
#include <PubSubClient.h>
#endif
#include <SPI.h>
#include <string.h>
#include "aJSON.h"
@@ -198,6 +206,9 @@ extern Streamlog errorSerial;
#include "stdarg.h"
#include "item.h"
#include "inputs.h"
#ifdef CANDRV
#include <candriver.h>
#endif
#ifdef _artnet
extern Artnet *artnet;
@@ -218,7 +229,11 @@ enum lan_status {
RECONNECT = 13,
READ_RE_CONFIG = 14,
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;
@@ -230,11 +245,18 @@ typedef union {
bool isNotRetainingStatus();
#if not defined (NOIP)
void mqttCallback(char *topic, byte *payload, unsigned int length);
void printMACAddress();
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
void Changed(int i, DeviceAddress addr, float currentTemp);
@@ -246,7 +268,7 @@ int cmdFunctionHelp(int arg_cnt, char **args);
int cmdFunctionKill(int arg_cnt, char **args);
void applyConfig();
bool applyConfig();
int cmdFunctionLoad(int arg_cnt, char **args);
@@ -261,6 +283,8 @@ int cmdFunctionGet(int arg_cnt, char **args);
int cmdFunctionLoglevel(int arg_cnt, char **args);
void printBool(bool arg);
int cmdFunctionSave(int arg_cnt, char **args);
/*
void saveFlash(short n, char *str);
@@ -271,7 +295,7 @@ void saveFlash(short n, IPAddress& ip);
int ipLoadFromFlash(short n, IPAddress &ip);
*/
int loadConfigFromHttp();
void preTransmission();
@@ -290,6 +314,7 @@ void inputLoop(short);
void inputSensorsLoop();
void inputSetup(void);
void inputStop(void);
void pollingLoop(void);
@@ -303,8 +328,6 @@ void printConfigSummary();
void setupCmdArduino();
void setupMacAddress();
void printFirmwareVersionAndBuildOptions();
bool IsThermostat(const aJsonObject *item);
@@ -313,14 +336,13 @@ bool disabledDisconnected(const aJsonObject *thermoExtensionArray, int thermoLat
void resetHard();
void onInitialStateInitLAN();
void ip_ready_config_loaded_connecting_to_broker();
bool cleanConf(short locksAlowed=0);
void printCurentLanConfig();
void onMQTTConnect();
int16_t attachMaturaTimer();
void setFirstBroker();
void setNextBroker();
//void printFreeRam();

View File

@@ -16,13 +16,13 @@
#if defined (ARDUINO_ARCH_ESP8266)
#if not defined (TWI_SCL) && defined (D1)
#define TWI_SCL D1
#endif
// #if not defined (TWI_SCL) && defined (D1)
// #define TWI_SCL D1
// #endif
#if not defined (WAK_PIN) && defined (D3)
#define WAK_PIN D3
#endif
// #if not defined (WAK_PIN) && defined (D3)
// #define WAK_PIN D3
// #endif
#if defined (TWI_SCL)
#define SCL_LOW() (GPES = (1 << TWI_SCL))
@@ -35,7 +35,7 @@
#if defined (ARDUINO_ARCH_ESP32)
#undef WAK_PIN
//#undef WAK_PIN
#undef SCL_RESET
//#ifndef WAK_PIN
//#define WAK_PIN 17
@@ -43,9 +43,9 @@
#endif
#if defined(ARDUINO_ARCH_AVR)
#ifndef WAK_PIN
#define WAK_PIN 3 // for LightHub UEXT SCS Pin
#endif
//#ifndef WAK_PIN
//#define WAK_PIN 3 // for LightHub UEXT SCS Pin
//#endif
#endif

View File

@@ -23,6 +23,8 @@ extern bool disableCMD;
#define AC_UNKNOWN CST_UNKNOWN
#define AC_IDLE CST_INITIALIZED
#define AC_SENDING CST_USER
#define AC_AWAITINGCMD CST_USER+1
#define AC_POLL CST_USER+2
//byte inCheck = 0;
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);}
publishTopic(item->itemArr->name, s_buffer,"/cmd");
SubmitParameters("cmd",icmd);
/*
if (store->power & 0x01)
publishTopic(item->itemArr->name, s_buffer,"/cmd");
@@ -323,6 +326,9 @@ if (!store)
return 0;}
memset(store->data,0,sizeof(acPersistent::data));
store->data[0]=255;
store->data[1]=255;
store->data[2]=0x22;
store->mode=0;
store->power=0;
store->inCheck=0;
@@ -393,18 +399,49 @@ case AC_SENDING:
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))
{
debugSerial.println(F("AC: Polling"));
SendData(qstn, sizeof(qstn)/sizeof(byte)); //Опрос кондиционера
}
*/
byte tmpdata[sizeof(store->data)];
if(ACSerial->available() >= 37){ //was 0
ACSerial->readBytes(store->data, 37);
ACSerial->readBytes(tmpdata, 37);
while(ACSerial->available()){
delay(2);
ACSerial->read();
@@ -413,24 +450,30 @@ if (cause!=POLLING_SLOW) return false;
debugSerial<<F("AC:")<<portNum<<F(" >> ");
for (int i=0; i < 37-1; i++)
{
if (store->data[i] < 10){
if (tmpdata[i] < 10){
debugSerial.print("0");
debugSerial.print(store->data[i], HEX);
debugSerial.print(tmpdata[i], HEX);
}
else
{
debugSerial.print(store->data[i], HEX);
debugSerial.print(tmpdata[i], HEX);
}
}
debugSerial.println('.');
uint8_t crc=getCRC(tmpdata,36);
if (store->data[36] != store->inCheck){
store->inCheck = store->data[36];
if (tmpdata[36] == crc)
{
debugSerial<<F("AC: OK")<<endl;
if (tmpdata[36] != store->inCheck)
{ //Updated
store->inCheck = tmpdata[36];
memcpy(store->data,tmpdata,sizeof(store->data));
InsertData(store->data, 37);
debugSerial<<F("AC: OK");
}
debugSerial.println();
}
else debugSerial<<F("AC: Bad CRC")<<endl;
}
return true;
};
@@ -468,6 +511,10 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
case S_CMD:
// s_mode[0]='\0';
store->timestamp=millisNZ();
setStatus(AC_AWAITINGCMD);
switch (cmd.getCmd())
{
case CMD_ON:
@@ -475,7 +522,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_POWER] = store->power;
store->data[B_POWER] |= 1;
SendData(on, sizeof(on)/sizeof(byte));
// publishTopic(item->itemArr->name,"ON","/cmd");
//publishTopic(item->itemArr->name,"ON","/cmd"); //
return 1;
break;
case CMD_OFF:
@@ -483,7 +530,7 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_POWER] = store->power;
store->data[B_POWER] &= ~1;
SendData(off, sizeof(off)/sizeof(byte));
// publishTopic(item->itemArr->name,"OFF","/cmd");
publishTopic(item->itemArr->name,"OFF","/cmd"); //
return 1;
break;
case CMD_AUTO:
@@ -549,9 +596,43 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute, bool authorized)
store->data[B_FAN_SPD] = 2;
strcpy_P(s_speed,LOW_P);
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:
//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
}
publishTopic(item->itemArr->name,s_speed,"/fan");

View File

@@ -35,7 +35,8 @@ public:
class out_AC : public abstractOut {
public:
out_AC(Item * _item):abstractOut(_item){store = (acPersistent *) item->getPersistent(); getConfig();};
out_AC():store(NULL),portNum(0),ACSerial(NULL){};
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (acPersistent *) item->getPersistent(); getConfig();} else store = NULL;};
void getConfig();
int Setup() override;
int Poll(short cause) override;

View File

@@ -91,6 +91,7 @@ case S_CMD:
case CMD_AUTO:
case CMD_FAN:
case CMD_DRY:
case CMD_HEATCOOL:
if (!item->getExt())
{
item->setExt(millisNZ());

View File

@@ -8,8 +8,6 @@
class out_counter : public abstractOut {
public:
out_counter(Item * _item):abstractOut(_item){};
int Setup() override;
int Poll(short cause) override;
int Stop() override;

View File

@@ -9,14 +9,10 @@
class out_dmx : public colorChannel {
public:
out_dmx(Item * _item):colorChannel(_item){};
int Setup() override;
int Stop() override;
int getChanType() override;
// int Ctrl(itemCmd cmd, char* subItem=NULL) override;
// int PixelCtrl(itemCmd cmd) override;
virtual int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false) override;
protected:

View File

@@ -346,6 +346,7 @@ if (!getConfig()) return 0;
break;
default:
store->timestamp = millisNZ();
setStatus(CST_INITIALIZED);
}

View File

@@ -42,13 +42,15 @@ public:
class out_Mercury : public abstractOut {
public:
out_Mercury(Item * _item):abstractOut(_item){store = (mercuryPersistent *) item->getPersistent();};
//out_Mercury(Item * _item):abstractOut(_item){store = (mercuryPersistent *) item->getPersistent();};
out_Mercury():store(NULL){};
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (mercuryPersistent *) item->getPersistent();} else store = NULL;};
int Setup() override;
int Poll(short cause) override;
int Stop() override;
int getChanType() override;
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
//int getDefaultStorageType(){return ST_INT32;};
protected:

View File

@@ -60,47 +60,18 @@ const reg_t regSize_P[] PROGMEM =
} ;
#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);
}
/**
* @brief Меняет порядок байтов в 16-битном числе.
* @param x Входное число.
* @return Число с изменённым порядком байтов.
*/
uint16_t swap (uint16_t x) {return ((x & 0xff) << 8) | ((x & 0xff00) >> 8);}
/**
* @brief Преобразует строку в тип регистра.
* @param str Строка с типом регистра.
* @return Код типа регистра.
*/
int str2regSize(char * str)
{
for(uint8_t i=0; i<regSizeNum && str;i++)
@@ -109,6 +80,62 @@ int str2regSize(char * str)
return (int) PAR_I16;
}
//TODO irs etc
/**
* @brief Получает имя параметра по номеру регистра.
* @param parameters JSON-объект с параметрами.
* @param regnum Номер регистра.
* @return Имя параметра или NULL.
*/
char * getParamNameByReg(aJsonObject * parameters, int regnum)
{
if (!parameters) return NULL;
aJsonObject * i = parameters->child;
while (i)
{
aJsonObject * regObj = aJson.getObjectItem(i, "reg");
if (regObj && regObj->type == aJson_Int && regObj->valueint == regnum)
{
debugSerial<<F("MBUS: ")<<i->name<<F(" added by num ")<<regnum<<endl;
return i->name;
}
i=i->next;
}
return NULL;
}
/**
* @brief Проверяет наличие действия в JSON-объекте.
* @param execObj JSON-объект.
* @return true, если действие найдено, иначе false.
*/
bool haveAction(aJsonObject * execObj)
{
aJsonObject * j = execObj->child;
switch (execObj->type)
{
case aJson_Object:
while (j)
{
if (j->name && *j->name && (*j->name != '@')) return true;
j=j->next;
}
break;
case aJson_Array:
while (j)
{
if (haveAction(j)) return true;
j=j->next;
}
}
return false;
}
/**
* @brief Загружает и применяет конфигурацию Modbus.
* @return true, если конфигурация успешно загружена, иначе false.
*/
bool out_Modbus::getConfig()
{
// Retrieve and store template values from global modbus settings
@@ -163,11 +190,136 @@ bool out_Modbus::getConfig()
else {store->pollingRegisters=NULL;store->pollingInterval = 1000;store->pollingIrs=NULL;}
store->parameters=aJson.getObjectItem(templateObj, "par");
// initializing @S where needed
if (store->parameters)
{
// Creating for parameters where prefetch required
debugSerial<<F("Adding prefetch regs:")<<endl;
aJsonObject * i = store->parameters->child;
while (i)
{
aJsonObject * prefetchObj = aJson.getObjectItem(i, "prefetch");
if (prefetchObj && prefetchObj->type == aJson_Boolean && prefetchObj->valuebool)
{
createLastMeasured(i->name);
}
i=i->next;
}
debugSerial<<F("Adding referred regs:")<<endl;
i = store->parameters->child;
// Creating for parameters used in references from another parameters
while (i)
{
aJsonObject * mapObj = aJson.getObjectItem(i, "map");
if (mapObj)
{
aJsonObject * defObj = aJson.getObjectItem(mapObj, "def");
if (defObj && defObj->type == aJson_Int)
{
createLastMeasured(getParamNameByReg(store->parameters,defObj->valueint));
}
if (defObj && defObj->type == aJson_String)
{
createLastMeasured(defObj->valuestring);
}
}
i=i->next;
}
debugSerial<<F("Adding regs with actions:")<<endl;
// Check - if action configured for object and create
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj)
{
i = itemParametersObj->child;
while (i)
{
if (haveAction(i)) createLastMeasured(i);
i=i->next;
}
}
}
return true;
//store->addr=item->getArg(0);
}
/**
* @brief Создаёт поле для хранения последнего измеренного значения по имени параметра.
* @param name Имя параметра.
* @return true, если успешно, иначе false.
*/
int out_Modbus::createLastMeasured(char * name)
{
if (!name) return false;
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
return createLastMeasured(aJson.getObjectItem(itemParametersObj,name));
}
/**
* @brief Создаёт поле для хранения последнего измеренного значения по JSON-объекту.
* @param execObj JSON-объект параметра.
* @return true, если успешно, иначе false.
*/
int out_Modbus::createLastMeasured(aJsonObject * execObj)
{
if (!execObj) return false;
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array)
{
markObj = execObj->child;
//storeLastValue = true;
}
if (!markObj) return false;
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
if (lastMeasured) return false;
debugSerial<<F("MBUS: Add @S: ")<<execObj->name<<endl;
aJson.addNumberToObject(markObj, "@S", (long) 0);
lastMeasured = aJson.getObjectItem(markObj,"@S");
if (!lastMeasured) return false;
lastMeasured->subtype |= MB_VALUE_OUTDATED;
return true;
}
/**
* @brief Получает объект последнего измеренного значения по имени параметра.
* @param name Имя параметра.
* @return JSON-объект или NULL.
*/
aJsonObject * out_Modbus::getLastMeasured(char * name)
{
if (!name) return NULL;
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
return getLastMeasured (aJson.getObjectItem(itemParametersObj,name));
}
/**
* @brief Получает объект последнего измеренного значения по JSON-объекту.
* @param execObj JSON-объект параметра.
* @return JSON-объект или NULL.
*/
aJsonObject * out_Modbus::getLastMeasured(aJsonObject * execObj)
{
if (!execObj) return NULL;
if (execObj->type == aJson_Array) execObj = execObj->child;
aJsonObject *lastMeasured = aJson.getObjectItem(execObj,"@S");
if (lastMeasured && lastMeasured->type == aJson_Int) return lastMeasured;
return NULL;
}
/**
* @brief Инициализирует канал Modbus и загружает конфигурацию.
* @return 1 при успехе, 0 при ошибке.
*/
int out_Modbus::Setup()
{
abstractOut::Setup();
@@ -186,11 +338,16 @@ if (getConfig())
else
{ errorSerial<<F("MBUS: config error")<<endl;
setStatus(CST_FAILED);
Stop();
return 0;
}
}
/**
* @brief Останавливает работу канала Modbus и освобождает ресурсы.
* @return 1 при успехе.
*/
int out_Modbus::Stop()
{
debugSerial.print("MBUS: De-Init ");
@@ -205,6 +362,13 @@ return 1;
/**
* @brief Читает данные из Modbus-устройства.
* @param reg Номер регистра.
* @param regType Тип регистра.
* @param count Количество регистров.
* @return true, если чтение успешно, иначе false.
*/
bool readModbus(uint16_t reg, int regType, int count)
{
uint8_t result;
@@ -223,6 +387,7 @@ switch (regType) {
break;
default:
debugSerial<<F("MBUS: Not supported reg type\n");
return false;
}
mbusSlenceTimer = millisNZ();
if (result != node.ku8MBSuccess) errorSerial<<F("MBUS: Polling error ")<<_HEX(result)<<endl;
@@ -231,6 +396,17 @@ return (result == node.ku8MBSuccess);
/**
* @brief Находит и обрабатывает регистр Modbus, выполняет сопоставление и действия.
* @param registerNum Номер регистра.
* @param posInBuffer Позиция в буфере ответа.
* @param regType Тип регистра.
* @param registerFrom Начальный регистр диапазона.
* @param registerTo Конечный регистр диапазона.
* @param doExecution Выполнять ли действие.
* @param submitParam Флаг для подавления повторных действий.
* @return Команда itemCmd с результатом.
*/
itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uint8_t regType, uint16_t registerFrom, uint16_t registerTo, bool doExecution, bool * submitParam)
{
aJsonObject * paramObj = store->parameters->child;
@@ -341,30 +517,38 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
switch (defMappingObj->type)
{
case aJson_Int: //register/coil/.. number
debugSerial<<F("Searching reg#")<<defMappingObj->valueint<<endl;
traceSerial<<F("MBUSD: Searching reg#")<<defMappingObj->valueint<<endl;
if ((defMappingObj->valueint>= registerFrom) && (defMappingObj->valueint<=registerTo))
{
mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut);
executeWithoutCheck=true;
traceSerial<<"MBUSD: recurrent check res: "<<"SRO:"<<submitRecurrentOut<<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();
}
else errorSerial<<F("reg# out of range")<<endl;
break;
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)
{
//Searching item param for nested mapping
aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring);
if (itemParObj)
{
//aJsonObject * markObj = execObj;
//if (execObj->type == aJson_Array) markObj = execObj->child;
//Retrive previous data
aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S");
if (lastMeasured && lastMeasured->type ==aJson_Int)
aJsonObject *lastMeasured = getLastMeasured(defMappingObj->valuestring);
if (lastMeasured)
{
debugSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
traceSerial<<F("LastKnown value: ")<<lastMeasured->valueint<<endl;
//Searching template param for nested mapping
aJsonObject * templateParObj = aJson.getObjectItem(store->parameters,defMappingObj->valuestring);
if (templateParObj)
@@ -411,42 +595,11 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
}
}
}
}
} //nested have lastMeasured
}
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
traceSerial << F("MBUSD: Mapped:")<<mappedParam.toString(buf,sizeof(buf))<<endl;
@@ -468,40 +621,54 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name);
if (execObj)
{
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array) markObj = execObj->child;
// if (!doExecution || haveAction(execObj)) //if no action in execObj - do not save last value to avoid confuse further recurrent check
// {
//Retrive previous data
aJsonObject *lastMeasured = aJson.getObjectItem(markObj,"@S");
aJsonObject *lastMeasured = getLastMeasured(execObj);
if (lastMeasured)
{
if (lastMeasured->type == aJson_Int)
{
if (lastMeasured->valueint == param)
{
//if recurrent call but value was readed before
if (!doExecution && !(lastMeasured->subtype & MB_VALUE_OUTDATED))
{
*submitParam=true; //never used
lastMeasured->subtype|=MB_VALUE_OUTDATED;
return mappedParam;
}
*submitParam=false; //supress repeating execution for same val
}
else
{
lastMeasured->valueint=param;
traceSerial<<"MBUS: Stored "<<param<<" to @S of "<<paramObj->name<<endl;
lastMeasured->subtype&=~MB_VALUE_OUTDATED;
}
}
}
else //No container to store value yet
{
debugSerial<<F("MBUS: Add @S: ")<<paramObj->name<<endl;
aJson.addNumberToObject(markObj, "@S", (long) param);
}
// }
if (executeWithoutCheck)
{
if (doExecution && (submitRecurrentOut || *submitParam)) executeCommand(execObj, -1, mappedParam);
if (doExecution && (submitRecurrentOut || *submitParam))
{
//debugSerial<<F("MBUS: exec ");mappedParam.debugOut();
executeCommand(execObj, -1, mappedParam);
*submitParam=true; //if requrrent check has submit smth - report it.
}
return mappedParam;
}
if (*submitParam)
if (*submitParam && doExecution)
{
// Compare with last submitted val (if @V NOT marked as NULL in config)
aJsonObject * markObj = execObj;
if (execObj->type == aJson_Array)
{
markObj = execObj->child;
//storeLastValue = true;
}
aJsonObject *settedValue = aJson.getObjectItem(markObj,"@V");
if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param))
{
@@ -510,22 +677,32 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin
}
else
{
if (doExecution) executeCommand(execObj, -1, mappedParam);
if (doExecution)
{
//debugSerial<<F("MBUS: exec ");mappedParam.debugOut();
executeCommand(execObj, -1, mappedParam);
}
// if param updated by device and no new value queued to send - update @V to avoid "Ignored - equal with setted val"
if (settedValue && !(execObj->subtype & MB_NEED_SEND))
settedValue->valueint=param;
}
}
}
}
} //to be executed
} //ExecObj
} //item Parameters
return mappedParam;
}
} //reg == regNum
paramObj=paramObj->next;
}
} //while
return itemCmd();
}
/**
* @brief Опрос Modbus-устройства по списку регистров.
* @param reg JSON-объект с регистрами.
* @param regType Тип регистра.
*/
void out_Modbus::pollModbus(aJsonObject * reg, int regType)
{
if (!reg) return;
@@ -550,7 +727,7 @@ return itemCmd();
int registerTo=aJson.getArrayItem(reg, 1)->valueint;
if (readModbus(registerFrom,regType,registerTo-registerFrom+1))
{ debugSerial<<endl;
{ traceSerial<<endl;
for(int i=registerFrom;i<=registerTo;i++)
{
findRegister(i,i-registerFrom,regType,registerFrom,registerTo);
@@ -564,6 +741,9 @@ return itemCmd();
}
}
/**
* @brief Инициализирует линию связи Modbus.
*/
void out_Modbus::initLine()
{
//store->serialParam=(USARTClass::USARTModes) SERIAL_8N1;
@@ -582,7 +762,13 @@ void out_Modbus::initLine()
node.begin(item->getArg(0), modbusSerial);
}
int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
/**
* @brief Отправляет значение в Modbus-устройство.
* @param paramName Имя параметра.
* @param outValue JSON-объект с отправляемым значением.
* @return 0 при успехе, отрицательное значение при ошибке.
*/
int out_Modbus::sendModbus(char * paramName, aJsonObject * outValue)
{
if (!store) {errorSerial<<F(" internal send error - no store")<<endl; return -1;}
@@ -595,54 +781,140 @@ int out_Modbus::sendModbus(char * paramName, int32_t value, uint8_t regType)
{
regObj = aJson.getObjectItem(templateParamObj, "coil");
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;
// int8_t regType = PAR_I16;
// aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
// if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
if (prefetchObj && (prefetchObj->type == aJson_Boolean) && prefetchObj->valuebool)
{
int modbusRegType = (outValue->subtype == PAR_COIL) ? MODBUS_COIL_REG_TYPE:MODBUS_HOLDING_REG_TYPE;
debugSerial<<F(" prefetch ")<<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);
mbusSlenceTimer = millisNZ();
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 = getLastMeasured(execObj);// 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
{
if (outValue->valueint == localBuffer)
{
debugSerial << F("MBUS:")<<paramName<< F("=")<<localBuffer<<F(": equal targert.")<<endl;
node.setDefaultResponseBuffer();
return -4;
}
debugSerial << F("MBUS:")<<paramName<< F(" val not changed. Continue")<<endl;
}
//}
}
}
}
#endif
}
node.setDefaultResponseBuffer();
}
switch(outValue->subtype) {
case PAR_U16:
case PAR_I16:
case PAR_TENS:
case PAR_100:
res = node.writeSingleRegister(regObj->valueint,value);
res = node.writeSingleRegister(regObj->valueint,outValue->valueint);
break;
break;
case PAR_I32:
case PAR_U32:
res = node.writeSingleRegister(regObj->valueint,swap(value & 0xFFFF));
res += node.writeSingleRegister(regObj->valueint+1,swap(value >> 16)) ;
res = node.writeSingleRegister(regObj->valueint,swap(outValue->valueint & 0xFFFF));
res += node.writeSingleRegister(regObj->valueint+1,swap(outValue->valueint >> 16)) ;
break;
case PAR_U8L:
case PAR_I8L:
res = node.writeSingleRegister(regObj->valueint,value & 0xFF);
res = node.writeSingleRegister(regObj->valueint,outValue->valueint & 0xFF);
break;
case PAR_U8H:
case PAR_I8H:
res = node.writeSingleRegister(regObj->valueint,(value & 0xFFFF)>> 8);
res = node.writeSingleRegister(regObj->valueint,(outValue->valueint & 0xFFFF)>> 8);
break;
case PAR_COIL:
res = node.writeSingleCoil (regObj->valueint,value);
res = node.writeSingleCoil (regObj->valueint,outValue->valueint);
break;
}
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);
}
/**
* @brief Осуществляет опрос и отправку команд Modbus.
* @param cause Причина вызова (например, медленный опрос).
* @return Интервал следующего опроса.
*/
int out_Modbus::Poll(short cause)
{
if (cause==POLLING_SLOW) return 0;
bool lineInitialized = false;
if (modbusBusy || (Status() != CST_INITIALIZED) || ( mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),100))) return 0;
if (modbusBusy || (Status() != CST_INITIALIZED) || ( mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200))) return 0;
aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2);
if (itemParametersObj && itemParametersObj->type ==aJson_Object)
@@ -667,23 +939,43 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
lineInitialized=true;
initLine();
}
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<" ";
switch (sendModbus(execObj->name,outValue->valueint,outValue->subtype))
int sendRes;
int savedValue;
bool needResend;
do
{
savedValue = outValue->valueint;
debugSerial<<"MBUS: SEND "<<item->itemArr->name<<"/"<<execObj->name<<"="<<outValue->valueint<<endl;
sendRes = sendModbus(execObj->name,outValue);
needResend = (savedValue != outValue->valueint);
while(needResend && mbusSlenceTimer && !isTimeOver(mbusSlenceTimer,millis(),200)) modbusIdle();
}
while (needResend); //repeat sending if target value changed while we're waited for mbus responce
switch (sendRes)
{
case 1: //success
execObj->subtype&=~ MB_NEED_SEND;
case -4: //equal tatget
//execObj->subtype&=~ MB_NEED_SEND;
execObj->subtype = 0;
onceSendOk=true;
///return 1; //relax
break;
case 0: //fault
execObj->subtype |= MB_SEND_ERROR;
errorSerial<<F("MBUS: ")<<execObj->name<<F(" send error. ");
errorSerial<<F("MBUS: ")<<item->itemArr->name<<"/"<<execObj->name<<F(" send error. ");
if ((execObj->subtype & 3) != MB_SEND_ATTEMPTS) execObj->subtype++;
errorSerial<<"Attempt: "<< (execObj->subtype & 3) <<endl;
errorSerial<<F("MBUS: ")<<item->itemArr->name<<"/"<<execObj->name<<" Attempt: "<< (execObj->subtype & 3) <<endl;
break;
case -3:
errorSerial<<F("MBUS: param ")<<item->itemArr->name<<"/"<<execObj->name<<F(" sending cancelled")<<endl;
//outValue->valueint=
//execObj->subtype&=~ MB_NEED_SEND;
execObj->subtype = 0;
break;
default: //param not found
errorSerial<<F("MBUS: param ")<<execObj->name<<F(" not found")<<endl;
errorSerial<<F("MBUS: param ")<<item->itemArr->name<<"/"<<execObj->name<<F(" not found")<<endl;
execObj->subtype&=~ MB_NEED_SEND;
}
}
@@ -694,7 +986,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
}
if (isTimeOver(store->timestamp,millis(),store->pollingInterval) && ( !mbusSlenceTimer || isTimeOver(mbusSlenceTimer,millis(),100)))
if (isTimeOver(store->timestamp,millis(),store->pollingInterval) && ( !mbusSlenceTimer || isTimeOver(mbusSlenceTimer,millis(),200)))
{
// Clean_up FLAG_SEND_ERROR flag
@@ -747,11 +1039,21 @@ if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store
return store->pollingInterval;
};
/**
* @brief Возвращает тип канала.
* @return CH_MBUS.
*/
int out_Modbus::getChanType()
{
return CH_MBUS;
}
/**
* @brief Отправляет команду itemCmd в Modbus по шаблону параметра.
* @param templateParamObj JSON-объект шаблона параметра.
* @param cmd Команда itemCmd.
* @return 1 при успехе, 0 при ошибке.
*/
int out_Modbus::sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd)
{
if (templateParamObj)
@@ -768,6 +1070,7 @@ int8_t regType = PAR_I16;
aJsonObject * typeObj = aJson.getObjectItem(templateParamObj, "type");
aJsonObject * mapObj = aJson.getObjectItem(templateParamObj, "map");
if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring);
switch(regType) {
case PAR_I16:
@@ -801,20 +1104,14 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,suffixStr);
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;
if (execObj->type == aJson_Array) markObj = execObj->child;
//Schedule update
execObj->subtype |= MB_NEED_SEND;
aJsonObject *outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) // Existant. Preserve original @type
{
@@ -829,15 +1126,17 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object)
outValue = aJson.getObjectItem(markObj,"@V");
if (outValue) outValue->subtype =regType & 0xF;
}
/* Conflict with pre-fetching
aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S");
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->subtype&=~MB_VALUE_OUTDATED;
}
*/
}
}
}
return 1;
@@ -851,6 +1150,14 @@ else return 0;
// 2. custom textual subItem
// 3. non-standard numeric suffix Code equal param id
/**
* @brief Унифицированное управление Modbus-каналом.
* @param cmd Команда itemCmd.
* @param subItem Имя подэлемента.
* @param toExecute Выполнять ли команду.
* @param authorized Авторизовано ли выполнение.
* @return Результат выполнения.
*/
int out_Modbus::Ctrl(itemCmd cmd, char* subItem, bool toExecute,bool authorized)
{
if (!store) return -1;

View File

@@ -31,8 +31,10 @@ public:
class out_Modbus : public abstractOut {
public:
//out_Modbus(Item * _item):abstractOut(_item){store = (mbPersistent *) item->getPersistent();};
out_Modbus():store(NULL){};
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (mbPersistent *) item->getPersistent(); } else store = NULL;};
out_Modbus(Item * _item):abstractOut(_item){store = (mbPersistent *) item->getPersistent();};
int Setup() override;
int Poll(short cause) override;
int Stop() override;
@@ -47,7 +49,11 @@ protected:
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 initLine();
int sendModbus(char * paramName, int32_t value, uint8_t regType);
int sendModbus(char * paramName, aJsonObject * outValue);
int sendItemCmd(aJsonObject *templateParamObj, itemCmd cmd);
int createLastMeasured(char * name);
int createLastMeasured(aJsonObject * execObj);
aJsonObject * getLastMeasured(char * name);
aJsonObject * getLastMeasured(aJsonObject * execObj);
};
#endif

View File

@@ -20,7 +20,9 @@ static int8_t motorQuote = MOTOR_QUOTE;
class out_Motor : public abstractOut {
public:
out_Motor(Item * _item):abstractOut(_item){getConfig();};
//out_Motor(Item * _item):abstractOut(_item){getConfig();};
//out_Motor(){};
void link(Item * _item){abstractOut::link(_item); if (_item) getConfig();};
int Setup() override;
int Poll(short cause) override;
int Stop() override;

View File

@@ -7,7 +7,19 @@
#include "item.h"
#include "main.h"
#include "utils.h"
void convert2float(aJsonObject * o)
{
if (!o) return;
switch (o->type)
{
case aJson_Int:
o->valuefloat = o->valueint;
o->type = aJson_Float;
break;
}
}
void out_Multivent::getConfig()
{
@@ -21,54 +33,228 @@ int out_Multivent::Setup()
abstractOut::Setup();
//getConfig();
//Expand Argument storage to 2
//for (int i = aJson.getArraySize(item->itemArg); i < 2; i++)
// aJson.addItemToArray(item->itemArg, aJson.createItem( (long int) 0));
//Allocate objects to store persistent data in config tree
if (gatesObj /*&& aJson.getArraySize(item->itemArg)>=2*/)
if (gatesObj)
{
aJsonObject * i = gatesObj->child;
while (i)
{
if (i->name && *i->name)
{
aJsonObject * setObj = aJson.getObjectItem(i, "set");
if (!setObj) aJson.addNumberToObject(i, "set", (long int) -1);
getCreateObject(i,"fan",-1L);
getCreateObject(i,"cmd",(long) CMD_OFF);
getCreateObject(i,"out",-1L);
//getCreateObject(i,"@C",(long) CMD_OFF);
aJsonObject * cmdObj = aJson.getObjectItem(i, "cmd");
if (!cmdObj) aJson.addNumberToObject(i, "cmd", (long int) -1);
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
if (pidObj && pidObj->type == aJson_Array && aJson.getArraySize(pidObj)>=3)
{
aJsonObject * setObj = getCreateObject(i,"set",(float) 20.0);
convert2float(setObj);
aJsonObject * valObj = getCreateObject(i,"val",(float) 20.0);
convert2float(valObj);
aJsonObject * poObj = getCreateObject(i,"po", (float) -2.0);
convert2float(poObj);
aJsonObject * outObj = aJson.getObjectItem(i, "out");
if (!outObj) aJson.addNumberToObject(i, "out", (long int) -1);
int direction = DIRECT;
float kP=getFloatFromJson(pidObj,0,1.0);
if (kP<0)
{
kP=-kP;
direction=REVERSE;
}
float kI=getFloatFromJson(pidObj,1);
float kD=getFloatFromJson(pidObj,2);
float dT=getFloatFromJson(pidObj,3,5.0);
pidObj->valueint = (long int) new PID (&valObj->valuefloat, &poObj->valuefloat, &setObj->valuefloat, kP, kI, kD, direction);
((PID*) pidObj->valueint)->SetMode (AUTOMATIC);
((PID*) pidObj->valueint)->SetSampleTime(dT*1000.0);
debugSerial << F ("VENT: PID P=")<<kP<<" I="<<kI<<" D="<<kD<< endl;
}
}
i=i->next;
}
debugSerial << F ("MultiVent init")<< endl;
debugSerial << F ("VENT: init")<< endl;
item->setExt(0);
setStatus(CST_INITIALIZED);
return 1;
}
debugSerial << F ("MultiVent config failed")<< endl;
debugSerial << F ("VENT: config failed")<< endl;
return 0;
}
int out_Multivent::Stop()
{
debugSerial << F ("Multivent De-Init") << endl;
debugSerial << F ("VENT: De-Init") << endl;
if (gatesObj)
{
aJsonObject * i = gatesObj->child;
while (i)
{
if (i->name && *i->name)
{
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
if (pidObj && pidObj->valueint)
{
delete ((PID *) pidObj->valueint);
pidObj->valueint = 0;//NULL;
}
}
i=i->next;
}
}
setStatus(CST_UNKNOWN);
return 1;
}
int out_Multivent::Poll(short cause)
{
return 0;
if (cause == POLLING_SLOW && item->getExt() && isTimeOver(item->getExt(),millisNZ(),60000L))
{
item->setExt(0);
//item->setCmd((isActive())?CMD_ON:CMD_OFF); // if AC temp unknown - change state to ON or OFF instead HEAT|COOL|FAN
aJsonObject * a = aJson.getObjectItem(aJson.getObjectItem(gatesObj, ""),"val");
if (a ) a->type = aJson_NULL;
}
if (gatesObj)
{
// metrics, collected from AC
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
float acTemp = getFloatFromJson(a,"val",NAN);
int actualCmd = getIntFromJson (a,"mode");
int actualMode = CMD_FAN;
if (acTemp>30.0) actualMode = CMD_HEAT;
else if (acTemp<15.0) actualMode = CMD_COOL;
aJsonObject * i = gatesObj->child;
int balance = 0;
bool ventRequested = false; //At least 1 ch requested FAN mode
while (i)
{
if (i->name && *i->name)
{
int cmd = getIntFromJson(i,"cmd");
float set = getIntFromJson(i,"set");
float val = getIntFromJson(i,"val");
int execCmd = 0;
switch (cmd)
{
case CMD_HEATCOOL:
{
if (set>val) execCmd = CMD_HEAT;
if (set<val) execCmd = CMD_COOL;
}
break;
case CMD_FAN:
ventRequested = true;
case CMD_AUTO: //Passive regulation mode
case CMD_COOL:
case CMD_HEAT:
case CMD_OFF:
//setValToJson(i,"@C",cmd);
execCmd = cmd;
break;
}
aJsonObject * pidObj = aJson.getObjectItem(i, "pid");
if (pidObj && pidObj->valueint)
{
PID * p = (PID *) pidObj->valueint;
if (p->Compute())
{
aJsonObject * poObj = aJson.getObjectItem(i,"po");
if (poObj && poObj->type == aJson_Float)
{
debugSerial<<F("VENT: ")
<<item->itemArr->name<<"/"<<i->name
<<F(" in:")<<p->GetIn()<<F(" set:")<<p->GetSet()<<F(" out:")<<p->GetOut()
<<" P:"<<p->GetKp()<<" I:"<<p->GetKi()<<" D:"<<p->GetKd()<<((p->GetDirection())?" Rev ":" Dir ")<<((p->GetMode())?"A":"M");
debugSerial<<endl;
switch (execCmd)
{
case CMD_AUTO: //Passive
switch (actualMode)
{
case CMD_HEAT:
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
break;
case CMD_COOL:
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
debugSerial<<F("VENT: PASS PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
}
break;
case CMD_HEAT:
((PID *) pidObj->valueint)->SetControllerDirection(DIRECT);
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set DIRECT mode")<<endl;
if (actualCmd==CMD_HEAT) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
//else?
balance+=poObj->valuefloat;
break;
case CMD_COOL:
//case CMD_FAN: // if PIB using for vent
//case CMD_ON: // AC temp unknown - assuming that PID used for vent
((PID *) pidObj->valueint)->SetControllerDirection(REVERSE);
debugSerial<<F("VENT: PID: ")<<item->itemArr->name<<"/"<<i->name<<F(" set REVERSE mode")<<endl;
if (actualCmd==CMD_COOL) (itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name);
//else ?
balance-=poObj->valuefloat;
break;
// if FAN_ONLY (AC report room temp regularry) - not use internal PID - let be on external control via /fan
}
}
}
}
}
i=i->next;
}//while
if (balance) debugSerial<<F("VENT: Chan balance=")<<balance<<endl;
if (balance>0) sendACcmd (CMD_HEAT);
else if (balance<0) sendACcmd (CMD_COOL);
else if (ventRequested) sendACcmd(CMD_FAN);
// else sendACcmd (CMD_OFF);
}
return 1;
};
int out_Multivent::sendACcmd (int cmd)
{
aJsonObject * a = aJson.getObjectItem(gatesObj, "");
if (!a) return 0;
int lastCmd = getIntFromJson(a,"@lastCmd");
int acCmd = getIntFromJson(a,"mode");
if (lastCmd && (acCmd != lastCmd)) {
//debugSerial<<"VENT: AC MODE changed manually to "<<item->getCmd()<<endl;
return 0;}
if (cmd == lastCmd) {
//debugSerial<<"VENT: AC MODE already same"<<endl;
return 0;}
executeCommand(a,-1,itemCmd().Cmd(cmd).setSuffix(S_CMD));
setValToJson(a,"@lastCmd",cmd);
return 1;
}
int out_Multivent::getChanType()
{
return CH_PWM;
return CH_THERMO; /////PWM
}
@@ -79,6 +265,41 @@ if (cmd.getCmd()==CMD_DISABLE || cmd.getCmd()==CMD_ENABLE) return 0;
int suffixCode = cmd.getSuffix();
if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it
if (!subItem) // feedback from shared AC
{
switch (suffixCode)
{
case S_VAL:
if (cmd.isValue())
{
debugSerial << F("VENT:")<<F("AC air temp: ")<< cmd.getFloat()<<endl;
item->setExt(millisNZ());
setValToJson(aJson.getObjectItem(gatesObj, ""),"val",cmd.getFloat());
}
return 1;
case S_FAN:
return 1;
case S_SET:
return 1;
case S_MODE:
debugSerial << F("VENT:")<<F("AC mode: ")<< cmd.getCmd()<<endl;
setValToJson(aJson.getObjectItem(gatesObj, ""),"mode",cmd.getCmd());
return 1;
case S_CMD:
return 1;
case S_TEMP:
debugSerial << F("VENT:")<<F("AC air roomtemp: ")<< cmd.getFloat()<<endl;
setValToJson(aJson.getObjectItem(gatesObj, ""),"roomtemp",cmd.getFloat());
return 1;
}
}
aJsonObject * i = NULL;
if (cmd.isCommand() && cmd.getSuffix()==S_FAN)
@@ -110,89 +331,144 @@ int maxPercent=0;
while (i)
{
aJsonObject * setObj=aJson.getObjectItem(i, "set");
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas");
if (setObj && cmdObj && setObj->type==aJson_Int && cmdObj->type==aJson_Int)
//aJsonObject * setObj=aJson.getObjectItem(i, "set");
aJsonObject * pidObj=aJson.getObjectItem(i, "pid");
if (fanObj && cmdObj && fanObj->type==aJson_Int && cmdObj->type==aJson_Int)
{
int V =aJson.getObjectItem(i,"V")->valueint;
int V = getIntFromJson(i,"V",60);
int requestedV=0;
if (subItem && !strcmp (i->name,subItem))
{
if (cmdObj && cmd.isCommand())
{
cmdObj->valueint = cmd.getCmd();
//publishTopic(i->name,cmdObj->valueint,"/set");
switch (cmd.getCmd())
{
case CMD_ON:
cmd.Percents255(setObj->valueint);
break;
case CMD_OFF:
cmd.Percents255(0);
}
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (setObj->valueint<20))
{
setObj->valueint=30;
cmd.Percents255(30);
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
}
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_COMMAND|FLAG_PARAMETERS,i->name);
}
else if (setObj && cmdObj && suffixCode == S_FAN && cmd.isValue())
switch (suffixCode)
{
case S_FAN:
if (cmd.isValue())
{
if (cmd.getInt())
{
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;
cmd.Cmd(CMD_ON);
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),FLAG_COMMAND,i->name);
}
setObj->valueint = cmd.getInt();
fanObj->valueint = cmd.getInt();
}
else
{
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
{ debugSerial<<"Turning OFF"<<endl;
if (cmdObj->valueint == CMD_ON)// != CMD_OFF && cmdObj->valueint != -1)
{ debugSerial<<"VENT: Turning OFF"<<endl;
cmdObj->valueint = CMD_OFF;
cmd.Cmd(CMD_OFF);
//if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),FLAG_COMMAND,i->name);
}
setObj->valueint = 0;
fanObj->valueint = 0;
}
//fanObj->valueint = cmd.getInt();
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS|FLAG_COMMAND,i->name);
}
else if (setObj && cmd.isValue())
if (!cmd.isCommand()) break; // if have command i FAN suffix - continue processing
case S_CMD:
if (cmd.isCommand())
{
setObj->valueint = cmd.getPercents255();
//publishTopic(i->name,setObj->valueint,"/set");
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
long sendFlags = 0;
switch (cmd.getCmd())
{
case CMD_ON:
cmd.Percents255(fanObj->valueint);
cmd.setSuffix(S_FAN);
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
cmdObj->valueint = cmd.getCmd();
break;
case CMD_OFF:
cmd.Percents255(0);
cmd.setSuffix(S_FAN);
sendFlags |= FLAG_COMMAND | FLAG_PARAMETERS;
cmdObj->valueint = cmd.getCmd();
break;
case CMD_ENABLE:
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(AUTOMATIC);
sendFlags |= FLAG_FLAGS;
break;
case CMD_DISABLE:
if (pidObj && pidObj->valueint) ((PID *) pidObj->valueint)->SetMode(MANUAL);
sendFlags |= FLAG_FLAGS;
break;
case CMD_AUTO:
case CMD_HEATCOOL:
case CMD_COOL:
case CMD_HEAT:
case CMD_FAN:
case CMD_DRY:
sendFlags |= FLAG_COMMAND;
cmdObj->valueint = cmd.getCmd();
break;
//todo - halt-rest-xon-xoff-low-med-hi
}
if (isNotRetainingStatus() && (cmdObj->valueint == CMD_ON) && (fanObj->valueint<20))
{
fanObj->valueint=30;
cmd.Percents255(30);
//if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
}
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,sendFlags,i->name);
}
break;
case S_SET:
if (cmd.isValue())
{
setValToJson(i,"set",cmd.getFloat());
if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,FLAG_PARAMETERS,i->name);
}
break;
case S_VAL:
if (cmd.isValue())
{
debugSerial<<F("VENT: value ")<<cmd.getFloat()<<endl;
setValToJson(i,"val",cmd.getFloat());
}
return 1;
break;
default:
break;
}
if (cascadeObj) executeCommand(cascadeObj,-1,cmd);
}
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1)
{
requestedV=V*setObj->valueint;
requestedV=V*fanObj->valueint;
activeV+=requestedV;
if (setObj->valueint>maxPercent )
if (fanObj->valueint>maxPercent )
{
maxRequestedV=requestedV;
maxV=V;
maxPercent=setObj->valueint;
maxPercent=fanObj->valueint;
}
}
totalV+=V;
@@ -204,9 +480,15 @@ while (i)
if (!totalV) return 0;
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));
executeCommand(aJson.getObjectItem(gatesObj, ""),-1,itemCmd().Percents255(fanV).setSuffix(S_FAN));
/*
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
if (!fanV) return 1;
@@ -216,20 +498,22 @@ if (gatesObj) i = gatesObj->child; //Pass 2: re-distribute airflow
while (i)
{
int V =aJson.getObjectItem(i,"V")->valueint;
int V = getIntFromJson(i,"V",60);
aJsonObject * outObj=aJson.getObjectItem(i, "out");
aJsonObject * setObj=aJson.getObjectItem(i, "set");
aJsonObject * fanObj=aJson.getObjectItem(i, "fan");
aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd");
if (outObj && setObj && cmdObj && outObj->type==aJson_Int && setObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
if (outObj && fanObj && cmdObj && outObj->type==aJson_Int && fanObj->type==aJson_Int && cmdObj->type==aJson_Int && V)
{
long int out = 0;
if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV)
{
int requestedV=V*setObj->valueint;
int requestedV=V*fanObj->valueint;
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

@@ -4,6 +4,7 @@
#include <abstractout.h>
#include <item.h>
#include "itemCmd.h"
#include <PID_v1.h>
//static int8_t motorQuote = 0;
@@ -11,7 +12,9 @@
class out_Multivent : public abstractOut {
public:
out_Multivent(Item * _item):abstractOut(_item){getConfig();};
//out_Multivent(Item * _item):abstractOut(_item){getConfig();};
//out_Multivent(){};
void link(Item * _item){abstractOut::link(_item); if (_item) getConfig();};
int Setup() override;
int Poll(short cause) override;
int Stop() override;
@@ -21,6 +24,8 @@ public:
int Ctrl(itemCmd cmd, char* subItem=NULL, bool toExecute=true, bool authorized = false) override;
protected:
void getConfig();
int sendACcmd (int cmd);
aJsonObject * gatesObj;
//float acTemp;
};
#endif

View File

@@ -171,7 +171,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
if (store->alarmArmed) debugSerial << F(" <ALM>");
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);
@@ -185,7 +185,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm
item->clearFlag(FLAG_ACTION_NEEDED);
itemCmd value((float) (store->output));
value.setSuffix(S_SET);
//value.setSuffix(S_SET);
executeCommand(oCmd,-1,value);
store->prevOut=store->output;
}
@@ -334,32 +334,39 @@ case S_CTRL:
switch (command)
{
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_HEAT:
case CMD_COOL:
case CMD_AUTO:
case CMD_FAN:
case CMD_DRY:
executeCommand(oCmd,-1,value);
case CMD_HEATCOOL:
executeCommand(oCmd,-1,itemCmd().Cmd((item->getFlag(FLAG_DISABLED))?CMD_DISABLE:CMD_ENABLE));
executeCommand(oCmd,-1,value);
item->SendStatus(FLAG_FLAGS);
return 1;
case CMD_ENABLE:
//item->setCmd(CMD_ENABLE);
//item->SendStatus(FLAG_COMMAND);
if (isNotRetainingStatus())
{
item->setCmd(CMD_ON);
item->SendStatus(FLAG_COMMAND);
}
item->setFlag(FLAG_ACTION_NEEDED);
executeCommand(oCmd,-1,value);
if (isActive()) executeCommand(oCmd,-1,itemCmd().Cmd((CMD_ON)));
store->prevOut=-2.0;
return 1;
case CMD_DISABLE:
//item->setCmd(CMD_DISABLE);
//item->SendStatus(FLAG_COMMAND);
executeCommand(oCmd,-1,value);
if (!isActive()) executeCommand(oCmd,-1,itemCmd().Cmd((CMD_OFF)));
return 1;
/*
case CMD_OFF:

View File

@@ -11,9 +11,9 @@
class pidPersistent : public chPersistent {
public:
PID * pid;
double output;
double input;
double setpoint;
iotype output;
iotype input;
iotype setpoint;
float prevOut;
uint32_t alarmTimer;
bool alarmArmed;
@@ -25,7 +25,10 @@ public:
class out_pid : public abstractOut {
public:
out_pid(Item * _item):abstractOut(_item){store = (pidPersistent *) item->getPersistent();};
//out_pid(Item * _item):abstractOut(_item){store = (pidPersistent *) item->getPersistent();};
out_pid():store(NULL){};
void link(Item * _item){abstractOut::link(_item); if (_item) {store = (pidPersistent *) item->getPersistent();} else store = NULL;};
int Setup() override;
int Poll(short cause) override;
int Stop() override;

View File

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

View File

@@ -10,7 +10,7 @@
class out_pwm : public colorChannel {
public:
out_pwm(Item * _item):colorChannel(_item){numChannels=0;};
// out_pwm():numChannels(0){};
int Setup() override;
int Stop() override;
@@ -19,7 +19,7 @@ public:
//int Ctrl(itemCmd cmd, char* subItem=NULL) override;
int PixelCtrl(itemCmd cmd, char* subItem=NULL, bool show=true, bool authorized = false ) override;
protected:
short numChannels;
//protected:
// short numChannels;
};
#endif

View File

@@ -35,15 +35,15 @@ int out_relay::Setup()
{
abstractOut::Setup();
debugSerial<<F("Relay-Out #")<<pin<<F(" init")<<endl;
if (isProtectedPin(pin)) {errorSerial<<F("pin disabled")<<endl;return 0;}
debugSerial<<F("relayCtr: ")<<F("pin#")<<pin<<F(" init")<<endl;
if (isProtectedPin(pin)) {errorSerial<<F("relayCtr: ")<<F("pin disabled")<<endl;return 0;}
pinMode(pin, OUTPUT);
digitalWrite(pin,INACTIVE);
if (item) item->setExt(0);
//if (item->getCmd()) item->setFlag(FLAG_COMMAND);
//if (item->itemVal) item->setFlag(FLAG_PARAMETERS);
setStatus(CST_INITIALIZED);
if (item->isActive()>0) ///????
if (item && (item->isActive()>0)) ///????
{
item->setExt(millisNZ());
}
@@ -52,7 +52,7 @@ return 1;
int out_relay::Stop()
{
debugSerial<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
debugSerial<<F("relayCtr: ")<<F("Relay-Out #")<<pin<<F(" stop")<<endl;
pinMode(pin, INPUT);
setStatus(CST_UNKNOWN);
return 1;
@@ -60,39 +60,12 @@ return 1;
void out_relay::relay(bool state)
{
char subtopic[10]="/";
char val[10];
digitalWrite(pin,(state)?ACTIVE:INACTIVE);
if (period<1000) return;
debugSerial<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
debugSerial<<F("relayCtr: ")<<F("Out ")<<pin<<F(" is ")<<(state)<<endl;
pubAction(state);
//debugSerial << F("OUT: ")<<F("pub action ") << F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
strcat_P(subtopic,action_P);
short cmd=item->getCmd();
if (state)
switch(cmd)
{
case CMD_COOL:
strcpy_P(val,cooling_P);
break;
//case CMD_AUTO:
//case CMD_HEAT:
//case CMD_ON:
//
// break;
case CMD_DRY:
strcpy_P(val,drying_P);
break;
case CMD_FAN:
strcpy_P(val,fan_P);
break;
default:
strcpy_P(val,heating_P);
}
else //turned off
if (cmd==CMD_OFF) strcpy_P(val,off_P);
else strcpy_P(val,idle_P);
debugSerial << F("pub action ") << publishTopic(item->itemArr->name,val,subtopic)<<F(":")<<item->itemArr->name<<subtopic<<F("=>")<<val<<endl;
}
@@ -170,6 +143,7 @@ case S_SET:
case CMD_COOL:
case CMD_DRY:
case CMD_HEAT:
case CMD_HEATCOOL:
if (cmd.getPercents255() && !item->getExt()) item->setExt(millisNZ());
}
}
@@ -184,6 +158,7 @@ case S_CMD:
case CMD_AUTO:
case CMD_FAN:
case CMD_DRY:
case CMD_HEATCOOL:
if (!item->getExt())
{
item->setExt(millisNZ());
@@ -197,11 +172,11 @@ case S_CMD:
return 1;
default:
debugSerial<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
debugSerial<<F("relayCtr: ")<<F("Unknown cmd ")<<cmd.getCmd()<<endl;
} //switch cmd
default:
debugSerial<<F("Unknown suffix ")<<suffixCode<<endl;
debugSerial<<F("relayCtr: ")<<F("Unknown suffix ")<<suffixCode<<endl;
} //switch suffix
return 0;

Some files were not shown because too many files have changed in this diff Show More