diff --git a/app/firmwares/alux_nemo.hex b/app/firmwares/alux_nemo.hex new file mode 100644 index 000000000..5e06297f7 --- /dev/null +++ b/app/firmwares/alux_nemo.hex @@ -0,0 +1,1413 @@ +:100000000C9415070C9432070C9432070C943207A9 +:100010000C94611D0C9432070C9432070C94320737 +:100020000C9432070C94B21D0C9432070C943207D6 +:100030000C9432070C9432070C9432070C9432075C +:100040000C9486120C9432070C94D7100C9432073F +:100050000C94FE100C9495140C9432070C943207F7 +:100060000C9434070C9432070C9432070C9432072A +:100070000C94B0100C9432070C9432070C94320795 +:100080000C9432070C9432070C9432070C9432070C +:100090000C9432070C9432070C9432070C943207FC +:1000A0000C9432070C9432070C9432070C943207EC +:1000B0000C9432074F079D079D079D079D079D07DD +:1000C0009D079D074F079D079D079D079D079D075E +:1000D0009D079D0751079D079D079D079D079D074C +:1000E0009D079D079D079D079D079D079D079D07F0 +:1000F0009D079D0751079D079D079D079D079D072C +:100100009D079D079D079D079D079D079D079D07CF +:100110009D079D0799079D079D079D079D079D07C3 +:100120009D079D0778079D079D079D079D079D07D4 +:100130009D079D079D079D079D079D079D079D079F +:100140009D079D076C079D079D079D079D079D07C0 +:100150009D079D078A075E0FAB10AB10AB10AB106D +:10016000AB10AB10AB10AB10AB10890F980FAB10EE +:10017000AB10AB10AB10AB10AB10AB10AB10B70F9C +:10018000BD0FCA0FD00FAB10AB10AB10AB10AB1044 +:10019000AB10DE0FAB10AB10AB10AB10AB10AB1055 +:1001A000AB10AB10AB10FB0F0A10AB10AB10AB10C9 +:1001B000AB10AB10AB10AB10AB10AB107A108710BC +:1001C00096109610961096109610961096109610FF +:1001D0009C10A410084AD73B3BCE016E84BCBFFDE7 +:1001E000C12F3D6C74319ABD56833DDA3D00C77F07 +:1001F00011BED9E4BB4C3E916BAAAABE00000080A0 +:100200003F003435300034353000672F600034351E +:100210006000DC273000DC2730003B2AC00034358A +:10022000300034353000672F6000343560008323A0 +:10023000300083233000DC27C000343530003435F3 +:1002400030009A1A6000A31F6000DC2760003B2A80 +:100250006000672F2001DC1D3000DC1D3000A31F73 +:100260006000DC2760008323300083233000DC271C +:10027000C000000060000000800100008001FFFF5E +:10028000FFFFDC1D3000DC1D3000DC1D3000DC1DFC +:100290003000DC1D3000DC1D3000DC1D3000DC1DBA +:1002A0003000DC1D3000DC1D3000DC1D3000DC1DAA +:1002B0003000B3173000B3173000B3173000B31756 +:1002C0003000B3173000B31730005F1630005F16F0 +:1002D00030005F1630005F163000B31730009A1AF6 +:1002E0003000DC1D3000DC1D3000DC1D3000DC1D6A +:1002F0003000DC1D3000DC1D3000DC1D3000DC1D5A +:100300003000DC1D3000DC1D3000DC1D3000DC1D49 +:100310003000B3173000B3173000B3173000B317F5 +:100320003000B3173000B31730005F163000DC1D0B +:100330003000C11130005F16300000003000C111E4 +:100340003000EE1360005F163000B31760009A1A99 +:100350003000DC1D6000DC1D3000DC1D30009A1A0E +:100360003000DC1D300084216000842130008421B5 +:100370003000DC1D300084213000832360008323A3 +:1003800030008323600083233000EE1360005F168B +:100390003000B31760009A1A3000DC1D6000DC1DCD +:1003A0003000DC1D30009A1A3000DC1D3000842142 +:1003B00060008421300084213000DC1D3000842165 +:1003C000300083236000832330008323600000001B +:1003D0003000DC1D30002F1C30009A1A3000DC1D6C +:1003E00030002F1C30009A1A3000DC1D30002F1C0A +:1003F00030009A1A3000DC1D30002F1C30009A1A91 +:1004000030009A1A30001C193000B31730009A1AC5 +:1004100030001C193000B31730005F1630005F1633 +:1004200030005F1630005F163000B31730009A1AA4 +:100430003000DC1D30002F1C30009A1A3000DC1D0B +:1004400030002F1C30009A1A3000DC1D30002F1CA9 +:1004500030009A1A3000DC1D30002F1C30009A1A30 +:1004600030009A1A30001C193000B31730009A1A65 +:1004700030001C193000B31730005F163000DC1D4F +:10048000300083233000BE2C300000003000C1114A +:100490003000EE1360005F163000B31760009A1A48 +:1004A0003000DC1D6000DC1D3000DC1D30009A1ABD +:1004B0003000DC1D30008421600084213000842164 +:1004C0003000DC1D30008421300083236000832352 +:1004D00030008323600083233000EE1360005F163A +:1004E0003000B31760009A1A3000DC1D6000DC1D7C +:1004F0003000DC1D30009A1A3000DC1D30008421F1 +:1005000060008421300084213000DC1D3000842113 +:1005100030008323600083233000832360000000C9 +:100520003000000060000000800100008001FFFF3B +:10053000FFFFB31730001C193000B31730001C192F +:100540003000B3173000A31F30009A1A3000DC1DB2 +:1005500030008323600000003000B93B3000672F7B +:10056000300083233000A31F600000003000672F9D +:1005700030009F253000A31F3000DC1D600000000C +:100580003000672F3000B31730001C193000B3174C +:1005900030001C193000B3173000A31F30009A1A26 +:1005A0003000DC1D30008323600000003000B93BC8 +:1005B0003000672F300083233000A31F600000004D +:1005C0003000672F3000DC1D3000A31F3000832374 +:1005D000600000003000A31F3000DC1D30009A1ABC +:1005E0003000B317600000003000DC2730005F16D9 +:1005F0003000B31730009A1A600000003000BE2CA3 +:100600003000B31730009A1A3000DC1D6000000083 +:100610003000672F30009A1A3000DC1D3000A31F15 +:100620006000672F3000B3173000B3173000672F1A +:100630003000672F3000B3173000000030001C1965 +:100640003000B31730001C193000B31730001C19EC +:100650003000B3173000A31F30009A1A3000DC1DA1 +:1006600030008323600000003000B93B3000672F6A +:10067000300083233000A31F600000003000672F8C +:1006800030009F253000A31F3000DC1D60000000FB +:100690003000672F3000B31730001C193000B3173B +:1006A00030001C193000B3173000A31F30009A1A15 +:1006B0003000DC1D30008323600000003000B93BB7 +:1006C0003000672F300083233000A31F600000003C +:1006D0003000672F3000DC1D3000A31F3000832363 +:1006E000C000000060000000800100008001FFFFEA +:1006F000FFFFDC276000DC276000672F3000BE2C86 +:100700003000DC2760008323600083236000DC2747 +:10071000C000DC276000DC1D6000B31760009A1A7F +:100720003000DC1D30009A1A8001B3176000B31747 +:1007300060009A1A60009A1A6000DC1D60009A1A24 +:100740003000DC1D30008323600083236000DC2741 +:100750006000DC276000DC276000672F3000832307 +:100760003000B93B80013435600034356000672FBC +:100770006000B93B60003435600034356000672F9D +:100780006000DC27600083236000DC1D6000B3177D +:1007900060009A1A3000DC1D30009A1A8001B317ED +:1007A0006000B31760009A1A60009A1A6000DC1D9E +:1007B00060009A1A3000DC1D300083236000832320 +:1007C0006000DC276000DC276000DC276000672F0A +:1007D000300034353000B93B80010000600000007B +:1007E000800100008001FFFFFFFFB93B6000B93BC3 +:1007F0006000DC276000DC27600083236000832327 +:100800006000DC27C000BE2C6000BE2C6000672F9B +:100810006000672F60003435600034356000B93BFC +:10082000C000DC276000DC276000BE2C6000BE2C0E +:100830006000672F6000672F60003435C000DC2740 +:100840006000DC276000BE2C6000BE2C6000672FBB +:100850006000672F60003435C000B93B6000B93BD1 +:100860006000DC276000DC276000832360008323B6 +:100870006000DC27C000BE2C6000BE2C6000672F2B +:100880006000672F60003435600034356000B93B8C +:10089000C000000060000000800100008001FFFF38 +:1008A000FFFFB93B3000BE2C3000DC273000832333 +:1008B0003000DC273000BE2C3000DC2720018323F1 +:1008C0006000BE2C3000DC273000BE2C30003435F8 +:1008D0003000B93B2001B93B3000BE2C3000DC2792 +:1008E000300083233000DC273000BE2C3000DC27B2 +:1008F000200183236000BE2C3000DC27300034351B +:100900003000672F3000BE2C2001DC273000DC27B0 +:100910003000DC273000BE2C3000DC273000832381 +:100920003000BE2C20019A1A60009A1A3000DC1D9B +:10093000600083233000DC272001DC1D300083238E +:100940003000DC273000BE2C3000DC273000832351 +:10095000300034352001B93B6000BE2C3000672FD9 +:100960003000BE2C3000DC273000BE2C20010000FF +:1009700060000000800100008001FFFFFFFFB93B25 +:10098000900034353000672F9000B93B3000672F5E +:100990006000B93B6000672FC00034359000672FBE +:1009A0003000BE2C3000BE2C3000672F30003435B4 +:1009B0003000BE2C200100006000672F9000BE2C8C +:1009C0003000DC273000DC273000672F3000672F35 +:1009D0003000DC276000672F6000DC27C000BE2CE1 +:1009E0009000DC2730008323300083233000DC2795 +:1009F0003000BE2C30008323200100006000DC2783 +:100A00009000B93B300034353000672F3000BE2CE9 +:100A10003000DC27300083232001000060008323A6 +:100A2000900034353000672F3000BE2C3000DC27BA +:100A3000300083233000A31F200100006000A31FAB +:100A40009000672F3000BE2C30009F25300083239C +:100A50003000A31F3000DC1D2001A31F3000A31FA6 +:100A6000300083236000BE2C6000A31F6000DC27E1 +:100A70006000DC1D2001000060000000800100001B +:100A80008001FFFFFFFF0000000000000000007D6C +:100A90000000000000600060000000143E143E14DE +:100AA0000000122A7F2A24000061660833430000F8 +:100AB0003649552205000000506000000000001C6F +:100AC00022410000000041221C00000014083E08E2 +:100AD00014000008083E0808000000050600000099 +:100AE00000080808080800000003030000000002D6 +:100AF0000408102000003E4549513E00000010202F +:100B00007F00000021434549310000224149493618 +:100B100000000C14247F040000725151514E00005B +:100B20003E49494926000040404748700000364988 +:100B30004949360000324949493E00000036360036 +:100B400000000000353600000000081422410000BB +:100B50000014141414140000004122140800002092 +:100B60004045483000003E414D553D00003F48485B +:100B7000483F00007F4949493600003E414141223B +:100B800000007F4141413E00007F4949494100004A +:100B90007F4848484000003E4141492E00007F0800 +:100BA00008087F000000417F4100000006010101AC +:100BB0007E00007F0814224100007F010101010036 +:100BC000007F2018207F00007F2010087F00003E5B +:100BD0004141413E00007F4848483000003C4242CD +:100BE000423D00007F4848483700003249494926C5 +:100BF000000040407F404000007E0101017E000077 +:100C00007C0201027C00007F0204027F000041227E +:100C10001C2241000070080708700000434549513C +:100C2000610000007F410000000020100804020065 +:100C3000000000417F000000102040201000000153 +:100C40000101010100000040201000000002151504 +:100C5000150F00007F1111110E00000E111111115E +:100C600000000E1111117F00000E1515150C00006B +:100C700010103F50500000081515151E00007F0889 +:100C800010100F000000115F010000000201115E52 +:100C90000000007F040A1100000000417F010000F5 +:100CA000001F100F100F00001F0810100F00000E83 +:100CB0001111110E00001F14141408000008141460 +:100CC000141F0000001F0810100000091515150260 +:100CD000000010107E111100001E0101021F000013 +:100CE0001C0201021C00001E0106011E0000110A68 +:100CF000040A110000180505051E0000111315193E +:100D00001100000008364141000000007F00000093 +:100D10000041413608000000204020102000007FE4 +:100D20007F7F7F7F00000034020202340000320423 +:100D300004043200281006060610282012040404B9 +:100D4000122028100202021010101C1202121C1095 +:100D5000102812021228102010240A241020786073 +:100D600050480402010F03050910204040201009DB +:100D700005030F010204485060780810207F2010FE +:100D8000080804027F020408080808492A1C080809 +:100D90001C2A49080808081D3D7F3D1D0836777745 +:100DA00008777736081C3E7F3E1C08183C3E1F3EE5 +:100DB0003C181C22414141221C41221408142241AA +:100DC000060A1222120A067F41414141417F020771 +:100DD000077E201800033F2020437F0000001400FE +:100DE0007F007F00000008000000000010000400E9 +:100DF0000000200008000200002200000022000085 +:100E0000220008002200002A0000002A00201122EF +:100E10005C2211200808235C2308087F7F7F7F7FE6 +:100E20007F7F000000000000000011241FBECFEFF4 +:100E3000D8E0DEBFCDBF11E0A0E0B1E0E4E4F7E52B +:100E400002C005900D92A43DB107D9F724E0A4EDAE +:100E5000B1E001C01D92AA3CB207E1F70E94A924AB +:100E60000C94A02B0C9400001F920F920FB60F92BF +:100E700011242F933F938F939F93AF93BF93EF933F +:100E8000FF93E091B9008E2F90E0FC013897E13597 +:100E9000F10508F052C0E65AFF4F0C94C72A109291 +:100EA0002C02E0912C0280914F03E81770F481E04E +:100EB0008E0F80932C02F0E0E95AFB4F80818093E3 +:100EC000BB0085E88093BC003FC081E0809348046C +:100ED00084E98093BC0038C0E0912C0281E08E0F41 +:100EE00080932C028091BB00F0E0E95AFB4F808395 +:100EF00020912C0230E080914F0390E00197281759 +:100F0000390724F485EC8093BC001EC085E88093EB +:100F1000BC001AC08091BB00E0912C02F0E0E95ABD +:100F2000FB4F808381E08093480484E98093BC0078 +:100F30000BC085EA8093BC0007C08091B900809304 +:100F40004E0184E98093BC00FF91EF91BF91AF9176 +:100F50009F918F913F912F910F900FBE0F901F90F7 +:100F6000189588E48093B8001092B9008FEF8093B1 +:100F7000BB0084E08093BC0008958EE291E0ECEB2E +:100F8000F0E002C0019719F0208120FDFBCF809195 +:100F90004E010895CF93DF93EC012EE231E0ECEBAC +:100FA000F0E003C02150310919F0908190FDFACF93 +:100FB00060934F03888180935704888180FD12C01D +:100FC000623080F0FE013196A8E5B4E06250262F31 +:100FD00030E02E5F3F4F2C0F3D1F91919D93E21704 +:100FE000F307D9F71092600388EF80934E0185EAEA +:100FF0008093BC00DF91CF910895AC01ECEBF0E061 +:10100000908190FDFDCF80914804882389F066236C +:1010100079F0A7E5B4E0FA016150262F30E02F5FA8 +:101020003F4F240F351F9D919193E217F307D9F796 +:10103000809148040895CF93DF9300D01F92CDB7DD +:10104000DEB7880F89836A834B8363E0CE01019604 +:101050000E94CA070F900F900F90DF91CF910895D3 +:10106000BF92CF92DF92EF92FF920F931F93CF9395 +:10107000DF9300D0CDB7DEB79091BC0090FD2AC0C1 +:1010800030E02115310531F16A01B82EBB0C8B2DF2 +:101090008160E82E8A01C20ED31EF62EF80110825E +:1010A000B982FA8262E0CE0101960E94CA07E98203 +:1010B00062E0CE0101960E94CA0762E0CE0101966D +:1010C0000E94FD079A81F80191938F01F394EC152A +:1010D000FD0521F70F900F90DF91CF911F910F9198 +:1010E000FF90EF90DF90CF90BF900895CF92DF9266 +:1010F000EF92FF92C090B403D090B503E090B60396 +:10110000F090B703209178023091790240917A02F1 +:1011100050917B02C701B6010E945428882344F4F1 +:10112000C0927802D0927902E0927A02F0927B0229 +:1011300020917402309175024091760250917702AD +:10114000C701B6010E94DA29181644F4C09274024D +:10115000D0927502E0927602F0927702C0905B0323 +:10116000D0905C03E0905D03F0905E0320917002EC +:10117000309171024091720250917302C701B60121 +:101180000E945428882344F4C0927002D0927102C5 +:10119000E0927202F092730220916C0230916D0223 +:1011A00040916E0250916F02C701B6010E94DA2988 +:1011B000181644F4C0926C02D0926D02E0926E0256 +:1011C000F0926F02C090A703D090A803E090A9030B +:1011D000F090AA03209168023091690240916A025E +:1011E00050916B02C701B6010E945428882344F431 +:1011F000C0926802D0926902E0926A02F0926B0299 +:10120000209164023091650240916602509167021C +:10121000C701B6010E94DA29181644F4C09264028C +:10122000D0926502E0926602F0926702FF90EF9022 +:10123000DF90CF9008958091B4039091B503A09171 +:10124000B603B091B7038093780290937902A0938C +:101250007A02B0937B028093740290937502A093FC +:101260007602B093770280915B0390915C03A0912A +:101270005D03B0915E038093700290937102A0931E +:101280007202B093730280936C0290936D02A093EC +:101290006E02B0936F028091A7039091A803A09172 +:1012A000A903B091AA038093680290936902A09366 +:1012B0006A02B0936B028093640290936502A093DC +:1012C0006602B09367020895882319F0813071F0A7 +:1012D00019C046EF58E26CE97FE34093BD04509398 +:1012E000BE046093BF047093C0040CC043E353E397 +:1012F0006BE870E44093BD045093BE046093BF0458 +:101300007093C004482F4295407F69E08DE00E94B1 +:101310001B080895623308F079C06150823031F5BE +:1013200085E2689F912D1124862F891B8695890F50 +:1013300086958695E82FF0E0DF01A45BBD4F2C91E8 +:10134000982F990F990F990F981B691B81E090E0D6 +:1013500002C0880F991F6A95E2F7922F982B9C93F1 +:10136000E454FC4F9081892B80830895813039F5B6 +:1013700085E2689F912D1124862F891B8695890F00 +:1013800086958695E82FF0E0DF01A45BBD4F2C9198 +:10139000982F990F990F990F981B691B81E090E086 +:1013A00002C0880F991F6A95E2F78095922F9823C3 +:1013B0009C93E454FC4F908189238083089583306B +:1013C00029F585E2689F912D1124862F891B86952A +:1013D000890F86958695E82FF0E0DF01A45BBD4F6D +:1013E0002C91982F990F990F990F981B691B81E0E9 +:1013F00090E002C0880F991F6A95E2F7922F982714 +:101400009C93E454FC4F908189278083089588231E +:1014100009F1815095E2899F212D1124982F921B6B +:101420009695920F96959695E92FF0E0E45BFD4F27 +:101430004081292F220F220F220F291B821B21E01E +:1014400030E0B90102C0660F771F8A95E2F7CB0141 +:101450008423089580E008958091C2049091C3048C +:1014600081359105B8F080913702811113C08091C8 +:10147000400180939E0481E080935A02E1ECF0E009 +:1014800080818064808382E48093C6001092C304CC +:101490001092C20480913F01811110923702089589 +:1014A0008F929F92AF92BF92CF92DF92EF92FF9274 +:1014B0000F931F93CF93DF93C0912A02D0912B02F9 +:1014C000FE01EE0FFF1FEE0FFF1FE35EFE4F808059 +:1014D0009180A280B38040E050E0C12CD12C7601F5 +:1014E00060E0A2E5B2E0AC1BBD0B2C91CA0130E07C +:1014F000042E02C0359527950A94E2F720FF23C0F9 +:101500004C175D0780F0FA01EE0FFF1FEE0FFF1F73 +:10151000EF5DFE4F0081118122813381C02AD12AE3 +:10152000E22AF32A0FC0880F991F880F991FFC0128 +:10153000E35EFE4F0081118122813381C02AD12ACE +:10154000E22AF32A6F5F4F5F5F4F4730510569F61C +:101550008091290281112EC08BB187718BB985B121 +:10156000837D85B970988AB187718D298AB984B1D4 +:10157000837D84B984B18C2984B98DB18E7F8E2905 +:101580008DB98BB133272B2D1A2D092D802B8BB9BB +:1015900085B1882985B94EB1C501AA27BB27482B3B +:1015A0004EB94AB1042B0AB924B1822A84B82DB1AC +:1015B000822B8DB920912902862F90E0422F022E96 +:1015C000000C550B4817590714F4611114C0809191 +:1015D0002A0290912B028630910530F40196909367 +:1015E0002B0280932A0204C010922B0210922A022E +:1015F0001092290203C02F5F20932902DF91CF911F +:101600001F910F91FF90EF90DF90CF90BF90AF9020 +:101610009F908F9008950F931F9380913D018111AA +:1016200079C0409131025091320260913302709141 +:101630003402452B462B472B61F490913E019130AB +:1016400021F497E0909335026BC09EE090933502B1 +:1016500067C0409144025091450260E070E0009103 +:10166000310210913202209133023091340204177A +:1016700015072607370708F060C010924502109240 +:10168000440280913D01811147C03091350280E0D4 +:1016900090E0432F50E0FA01E80FF91FE454FC4FAB +:1016A0002081FC01E45BFD4F20830196873091058A +:1016B00091F781E0830F809335029091360291116A +:1016C00002C026E001C020E040913E0190E030E001 +:1016D00057E0459F200D311D112428173907F4F4D8 +:1016E0001092350281E080933D0180914B028F5F23 +:1016F00080934B0280E090E0FC01E45BFD4F208191 +:10170000FC01E454FC4F2083019687309105A1F73A +:1017100081E013C080E011C081E00FC081E00DC006 +:1017200041E050E060E070E04093310250933202BB +:1017300060933302709334028CCF1F910F91089500 +:10174000CF93DF93DC01EA011092350287E0689FB6 +:10175000B00111246A5F7F4F20E030E090E0FD018E +:10176000E90FF11D50815F77F901ED53FC4F508374 +:101770009F5F292F30E0621773078CF7993020F0B4 +:1017800082E080933E0103C081E080933E0181E0CE +:101790008093360210923D01AE0160E070E040930C +:1017A0003102509332026093330270933402DF911E +:1017B000CF910895882399F110923502815027E046 +:1017C000829FC00111248A5D924F27E030E0FC0126 +:1017D00045915491F901E454FC4F408301962F5FE9 +:1017E0003F4F2E30310599F781E080933E01ECEBBD +:1017F000F3E016861786108A118A128A138A148AD1 +:101800008093360210923D01CB01A0E0B0E08093BE +:10181000310290933202A0933302B09334020895C0 +:10182000CF92DF92EF92FF920F931F93CF93DF93AC +:1018300000D000D01F92CDB7DEB7FC016623C9F0FF +:1018400080913D01882381F010923D018091260214 +:10185000909127028E179F07D9F010923502F093CE +:101860002702E093260214C0E0912602F09127029D +:101870000FC010923D018091260290912702E81737 +:10188000F90731F010923502F0932702E093260217 +:101890009F01329522952F7023273F702327A7E4BD +:1018A000B3E00E94CD2A8C011695079516950795F1 +:1018B000169507950D8320E137E2029FC001039F33 +:1018C000900D129F900D11249F01281B390B369506 +:1018D00027953695279536952795A5ECB0E20E9479 +:1018E000CD2A929582958F7089279F708927F82E2F +:1018F0008C839F01369527953695279536952795A4 +:101900000E94CD2A929582958F7089279F70892792 +:1019100068EE73E0869F9001879F300D969F300D93 +:101920001124CF01821B930B9C0136952795369588 +:101930002795ABE7B4E10E94CD2A96958795E82ECE +:101940008B839F0136952795369527950E94CD2A42 +:101950009695879564E6689F9001699F300D1124E4 +:10196000CF01821B930B9C01ADECBCEC0E94CD2AF5 +:10197000969587959695879596958795D82E8A837F +:101980009F010E94CD2A9695879596958795969565 +:1019900087959C01220F331F880F991F880F991F6D +:1019A000880F991F820F931FE81BF90BE983012B06 +:1019B00009F051C0F11052C0E11053C0D11054C011 +:1019C00001E010E053C0282F30E0FB01A591B49155 +:1019D000F901E454FC4FA0838F5F6F5F7F4F981332 +:1019E000F2CF892F0E151F05A1F0F80122918F016A +:1019F00030E0205F3F4FB901660F771F660F771FFA +:101A0000660F771F621B730B6A57754F97E0980F2D +:101A1000DACF9C2D990F990F990F9C198EE0890FA1 +:101A2000C394C0923E019B5EE82FF0E0E454FC4F6B +:101A300010828F5F9813F8CF10923D0110923602FA +:101A400060E070E0409331025093320260933302C1 +:101A50007093340218C005E010E008C004E010E004 +:101A600005C003E010E002C002E010E06801F1E010 +:101A7000CF1AD10881E090E08C0F9D1F080F191F2D +:101A80007C0187E0B2CF0F900F900F900F900F90D6 +:101A9000DF91CF911F910F91FF90EF90DF90CF904A +:101AA000089521E0209330029F7790934E03809316 +:101AB0004D03089591E090932F028F7780932E022B +:101AC0000895009741F020E42093800090938900CE +:101AD00080938800089510928000299A10928900BE +:101AE00010928800089580913002882399F081E057 +:101AF0008093250210923002109224021092230249 +:101B000080914D0390914E03892BA1F483E0809343 +:101B1000250247C080912502813061F030F082308B +:101B200029F1833009F044C03CC010922402109285 +:101B300023020895289A80914D0390914E030E94AC +:101B4000610D8091230290912402019690932402CA +:101B500080932302449760F1809125028F5F8093E8 +:101B60002502109224021092230208952898809151 +:101B700023029091240201969093240280932302E1 +:101B8000813D9740A8F0809125028F5F80932502C8 +:101B900080E090E00E94610D1092240210922302D6 +:101BA0000895289880E090E00E94610D109225022F +:101BB0000895CF93DF9380912F02882351F181E024 +:101BC0008093460210922F02109248021092470210 +:101BD00010924A021092490280912E02811119C07E +:101BE00085E08093460280914602823009F49AC0D3 +:101BF00038F4882309F47CC0813009F42EC132C145 +:101C0000843009F4D5C008F4A4C0853009F4F4C0C8 +:101C100029C180912E02813059F4E0914702F09160 +:101C20004802EE0FFF1FE258F64FC591D4914EC007 +:101C3000823059F4E0914702F0914802EE0FFF1F05 +:101C4000EE55F74FC591D49141C0833059F4E091DE +:101C50004702F0914802EE0FFF1FE651F84FC59181 +:101C6000D49134C0843059F4E0914702F091480295 +:101C7000EE0FFF1FEE50F94FC591D49127C085306C +:101C800059F4E0914702F0914802EE0FFF1FEE5C1D +:101C9000FA4FC591D4911AC0863059F4E0914702A9 +:101CA000F0914802EE0FFF1FEE57FD4FC591D49102 +:101CB0000DC0873009F0BDC0E0914702F0914802A5 +:101CC000EE0FFF1FEE5FFD4FC591D491809146024C +:101CD000823041F128F4882359F0813071F0C2C07C +:101CE000843009F46AC0D0F1853009F485C0BAC0E7 +:101CF0001092480210924702B5C0CE010E94610DB9 +:101D0000CD2B09F0289A80914702909148020196C4 +:101D10009093480280934702809146028F5F8093A0 +:101D20004602A0C08091490290914A020196909388 +:101D30004A0280934902449708F494C010924A02E0 +:101D400010924902809146028F5F80934602289844 +:101D500089C0C0E0D0E002C0C0E0D0E0809149027C +:101D600090914A02019690934A0280934902C5508D +:101D7000D04CCC0FDD1FCC0FDD1F8C179D0708F456 +:101D800071C080E090E00E94610D809147029091C7 +:101D900048020196909348028093470210924A02AB +:101DA00010924902809146028F5F809346025AC08A +:101DB000C0E0D0E002C0C0E0D0E080914902909144 +:101DC0004A02019690934A028093490210924A0275 +:101DD0001092490281E080934602219609F042C0A8 +:101DE00010924802109247021092460280915D02C2 +:101DF0008F5F80935D0236C0289880914902909150 +:101E00004A02019690934A02809349028D32914092 +:101E100048F180E090E00E94610D10924A02109219 +:101E20004902109246021EC080E090E00E94610DBF +:101E30006ACF80914602823009F474CF30F488234F +:101E400009F456CF813081F30DC0843009F4B3CF4B +:101E500008F482CF853081F205C080E090E00E94D6 +:101E6000610D51CFDF91CF910895E0ECF0E09081CA +:101E700095FFFDCF8093C6000895CF93DF93EC01CB +:101E80008881882339F0219681110E94350F89912C +:101E90008111FACFDF91CF910895262F30E0F9011B +:101EA000EF5DFD4F9081492F50E04F33510508F011 +:101EB00052C1FA01E555FF4F0C94C72A8A3A31F412 +:101EC000F901EF5DFD4F8AE0808308958B3131F495 +:101ED000F901EF5DFD4F84E180830895833611F0B1 +:101EE000843231F4F901EF5DFD4F8EE18083089576 +:101EF0008D3A31F4F901EF5DFD4F88E2808308955A +:101F00008B3209F02CC1F901EF5DFD4F83E3808333 +:101F10000895853541F4F901EF5DFD4F8BE0808335 +:101F2000109287020895F901EF5DFD4F1082089528 +:101F3000E0918702F0E0EE58FC4F808380918702A9 +:101F40008F5F80938702843008F409C1E2E7F3E0F1 +:101F5000408191818281D901AF5DBD4F1C92238167 +:101F6000940F890F8213FBC010925C020895F9014F +:101F7000EF5DFD4F85E180830895811106C0F90171 +:101F8000EF5DFD4F86E180830895F901EF5DFD4F20 +:101F900010820895F901EF5DFD4F87E18083089578 +:101FA0008E3009F0DCC08FB78F778FBFE0E6F0E0AE +:101FB00080818861808389E08083FFCF863311F040 +:101FC0008234A1F48091400180939E0481E080934B +:101FD0005A02E1ECF0E080818064808382E48093A7 +:101FE000C600F901EF5DFD4F10820895F901EF5D24 +:101FF000FD4F108208958A3D41F4F901EF5DFD4FD8 +:1020000089E28083109287020895F901EF5DFD4F08 +:102010001082089590917203911105C09091390238 +:10202000916090933902E0918702F0E0EE58FC4F06 +:102030008083809187028F5F8093870290917203E3 +:10204000981708F08CC08091720390E001971816E1 +:102050001906B4F480E090E070E060E0E2E7F3E0BD +:10206000DC01AD58BC4F8C91680F7F5F872F90E0EB +:10207000408150E041505109841795078CF301C00D +:1020800060E0F901EF5DFD4F1082E0917203F0E036 +:10209000EE58FC4F8081861362C08FE0809353021C +:1020A00010923B0210923C0210923D0210923E02AE +:1020B0008091720390E0019718161906BCF480E035 +:1020C00090E040E0E2E7F3E0DC01AD58BC4F2C913A +:1020D000DC01A159BB4F2C934F5F842F90E02081EE +:1020E00030E0215031098217930774F381E0809327 +:1020F000370208958E3431F4F901EF5DFD4F84E32A +:1021000080830895F901EF5DFD4F108208958134B9 +:1021100041F410928702F901EF5DFD4F85E3808362 +:102120000895F901EF5DFD4F10820895F901EF5D0B +:10213000FD4F9F5F9083089580936103F901EF5DE8 +:10214000FD4F8EE38083089580936203F901EF5D74 +:10215000FD4F10820895F901EF5DFD4F1082089543 +:102160001F920F920FB60F9211242F933F934F930C +:102170005F936F937F938F939F93AF93BF93EF93EF +:10218000FF938091CE0061E00E944D0FFF91EF918F +:10219000BF91AF919F918F917F916F915F914F917F +:1021A0003F912F910F900FBE0F901F9018951F9287 +:1021B0000F920FB60F9211242F933F934F935F937B +:1021C0006F937F938F939F93AF93BF93EF93FF93FF +:1021D0008091C60060E00E944D0FFF91EF91BF918A +:1021E000AF919F918F917F916F915F914F913F91AF +:1021F0002F910F900FBE0F901F9018951F920F9266 +:102200000FB60F9211248F93EF93FF938091C0002C +:1022100086FD1AC0E0911B0180915A028E1748F486 +:10222000E1ECF0E080818F7B808381E080931B0173 +:102230000BC0F0E0E356FB4F80818093C600809195 +:102240001B018F5F80931B01FF91EF918F910F9086 +:102250000FBE0F901F9018959091620280916202BC +:102260008F7020912002281769F010923B02109283 +:102270003C0210923D0210923E02809162028F70E9 +:102280008093200280911F0298130DC080911E023E +:1022900021E0280F20931E02882389F010921D024E +:1022A00090936B040CC080911D0221E0280F2093B5 +:1022B0001D02882321F010921E0290931F0290911C +:1022C0006B0480919C0489278093840290918402FE +:1022D00080916B04892380935003909184028091B4 +:1022E0009C0489238093B90380916B0480939C04A0 +:1022F000089580915B02882349F08E7F80935B0272 +:10230000109261021092600210925F02809150035D +:1023100080FF07C0809150038E7F8093500381E03F +:1023200001C080E090916102892B809361028091CD +:10233000500381FF07C0809150038D7F809350032D +:1023400082E001C080E090916102892B809361025C +:102350008091500382FF07C0809150038B7F809350 +:10236000500384E001C080E090916102892B80934A +:1023700061028091500383FF07C080915003877FE3 +:102380008093500388E001C080E090916102892B26 +:10239000809361028091500385FF07C080915003B4 +:1023A0008F7D8093500380E201C080E090916102B4 +:1023B000892B809361028091B90380FF07C08091CF +:1023C000B9038E7F8093B90381E001C080E09091D2 +:1023D0006002892B809360028091B90381FF07C05E +:1023E0008091B9038D7F8093B90382E001C080E0C2 +:1023F00090916002892B809360028091B90382FFE3 +:1024000007C08091B9038B7F8093B90384E001C03A +:1024100080E090916002892B809360028091B903E3 +:1024200083FF07C08091B903877F8093B90388E059 +:1024300001C080E090916002892B809360028091BE +:10244000B90385FF07C08091B9038F7D8093B903DD +:1024500080E201C080E090916002892B809360024D +:102460008091840280FF07C0809184028E7F8093D8 +:10247000840281E001C080E090915F02892B80930B +:102480005F028091840281FF07C0809184028D7F6A +:102490008093840282E001C080E090915F02892BEA +:1024A00080935F028091840282FF07C08091840242 +:1024B0008B7F8093840284E001C080E090915F0272 +:1024C000892B80935F028091840283FF07C08091F3 +:1024D0008402877F8093840288E001C080E090912D +:1024E0005F02892B80935F028091840285FF07C081 +:1024F000809184028F7D8093840280E201C080E01D +:1025000090915F02892B80935F0208951F920F9232 +:102510000FB60F9211242F933F934F935F936F93B6 +:102520007F938F939F93AF93BF93EF93FF9386B562 +:102530008A5186BD80914D0490914E049C012F5F7D +:102540003F4F30934E0420934D04813D974008F057 +:102550005C9A80914F04909150040196909350049E +:1025600080934F040E94791180911B0290911C026C +:102570009C012F5F3F4F30931C0220931B020A9750 +:1025800050F180914402909145020196909345024A +:102590008093440210921C0210921B0280915802F8 +:1025A0009091590201969093590280935802A895F0 +:1025B0008091560290915702019690935702809312 +:1025C00056028091540290915502019690935502C3 +:1025D000809354020AC080912D02811106C00E948E +:1025E0000B0B811102C00E94500AFF91EF91BF9125 +:1025F000AF919F918F917F916F915F914F913F919B +:102600002F910F900FBE0F901F9018958091850409 +:10261000882391F0809185040E94070A882311F095 +:1026200090E801C090E080911A028F5F80931A02B7 +:102630008F77892B80931902209162028091610229 +:102640003091600290915F022072220F220F30724F +:10265000322B8072880F282F232B9072892F90E0C5 +:1026600095958795822BEDE9F4E09AED9183209181 +:102670008502309186023383209185023091860253 +:1026800024832091490430914A04358320914904E0 +:1026900030914A0426832091B0033091B1033783EF +:1026A0002091B0033091B10320872091BA0330917B +:1026B000BB032187909143029287A3E5B3E0149670 +:1026C0009C911497938715969C911597948785876D +:1026D0008C918095868711968C911197809587872C +:1026E00012968C9112978095808B13968C91809581 +:1026F000818B909162022091610230E1939FC00131 +:102700001124922F9F70892B828B909160022091CF +:102710005F0230E1939FC0011124922F9F70892B9B +:10272000838B80911902848B8091A403858B2091E7 +:102730004B0280914C0340915D0290E1499FA001C2 +:1027400011244F73880F880F8C70842B90E4299F7D +:1027500090011124822B868B178A83E090E0DC01A4 +:10276000A356BB4F3C912789230F278B01968731B6 +:102770009105A9F785E180939F0487E180935A0230 +:10278000E1ECF0E08081806480838DEC8093C60072 +:1027900081E080935B02089580918502909186028A +:1027A0004E9754F4809185029091860221E0833EF9 +:1027B0009F4F1CF420E001C020E0809149049091DB +:1027C0004A044E97CCF48091490490914A042130F8 +:1027D000A9F4833E9F4FA4F08091B0039091B10380 +:1027E000873491057CF48091B0039091B1038A3BCA +:1027F0009F4F54F484E009C080E007C080E005C02A +:1028000080E003C088E001C080E02091490430915D +:102810004A042F31310514F0806408C02091490426 +:1028200030914A04223E3F4F0CF48068209185028B +:10283000309186022F31310514F0806208C020915A +:10284000850230918602223E3F4F0CF48061209138 +:10285000490430914A042F3431050CF082602091F4 +:10286000BA033091BB032A35310508F081608093AB +:1028700043020895843011F0823068F4729A109205 +:10288000420281E08093410284E680933F0282ED20 +:10289000809340020895873061F4729881E08093BC +:1028A00042021092410210923F0289ED8093400251 +:1028B0000895823069F4729881E080934202109208 +:1028C000410280E580933F0284ED809340020895A9 +:1028D000883069F4729881E080934202109241023C +:1028E0008FE080933F0284E6809340020895863013 +:1028F00069F472981092420281E08093410284E16F +:1029000080933F028CE8809340020895853061F403 +:10291000729881E0809341021092420282E3809398 +:102920003F0288EC8093400208951F920F920FB6E9 +:102930000F9211248F929F92AF92BF92CF92DF920B +:10294000EF92FF922F933F934F935F936F937F93F9 +:102950008F939F93AF93BF93CF93DF93EF93FF93A7 +:102960007894EAE7F0E080818773808380915E024B +:1029700080FD39C06091790080915E02893060F5F8 +:102980006F3508F46FE5C0915E02C695D0E0673EF2 +:1029900008F066EE70E080E090E00E94012920E0FF +:1029A00030E04EEB52E40E94752720E030E04FE724 +:1029B00053E40E94E72920E030E047E053E40E941E +:1029C000592820E030E0A9010E9476270E94D228F1 +:1029D000CD5ADC4F688307C0E0915E02E695F0E0D7 +:1029E000ED5AFC4F608380915E028A3009F077C017 +:1029F0008091580360913F02861718F46093580342 +:102A000008C09091580380914002891710F4809378 +:102A1000580370E080E090E00E9401296B017C0186 +:102A2000C3E5D3E06D8170E080E090E00E94012971 +:102A3000A70196010E94752720E030E04FE753E49C +:102A40000E94E7294B015C016091400270E080E048 +:102A500090E00E940129A70196010E9475279B0121 +:102A6000AC01C501B4010E94592820E030E0A90161 +:102A70000E9476270E94D2286D838091410288238C +:102A800019F08D8180958D838091580390E020917D +:102A9000D4013091D501821B930B9093D501809383 +:102AA000D4019C01992324F422273327281B390BB6 +:102AB000253631056CF0992334F080914C03815018 +:102AC00080934C0305C080914C038F5F80934C032F +:102AD0008091580390E09093D5018093D401809128 +:102AE0005E028F5F80935E028C3010F010925E0267 +:102AF000FF91EF91DF91CF91BF91AF919F918F9116 +:102B00007F916F915F914F913F912F91FF90EF9047 +:102B1000DF90CF90BF90AF909F908F900F900FBE9F +:102B20000F901F901895F999FECF92BD81BD60BDA1 +:102B3000FA9AF99A0895CF92DF92EF92FF920F934B +:102B40001F93CF93DF93EC018B01809128028111B9 +:102B50007AC088818E3609F076C08981853609F081 +:102B600072C08A818D3609F06EC08B818F3609F074 +:102B70006AC08C81883709F066C08D81893709F079 +:102B800062C08E818A3709F05EC08F818A3209F077 +:102B90005AC081E0809328020F2EF4ECCF2EF4E08F +:102BA000DF2EF02DF6012481358182E690E0821B34 +:102BB000930B0F2EF1E5EF2EF4E0FF2EF02DF70131 +:102BC0009583848384819581692F84EC90E00E94B1 +:102BD0009315F7016481758185EC90E00E9493154F +:102BE000F60180819181919581959109F7019183F9 +:102BF000808380819181692F80EC90E00E94931501 +:102C0000F7016081718181EC90E00E949315F601DB +:102C100082819381919581959109F70193838283B4 +:102C200082819381692F82EC90E00E949315F701D5 +:102C30006281738183EC90E00E9493156AEA86ECCE +:102C400090E00E9493151092350288818052803660 +:102C500058F5A0E077E0672F80E090E0262F30E085 +:102C6000488150E040525109FA01EE0FFF1FEE0F6C +:102C7000FF1FEE0FFF1FE41BF50BE80FF91FEA57CC +:102C8000F54F45915491F901E454FC4F40836F5F37 +:102C900001968730910511F7795F2196AF5F8881A2 +:102CA00080528036C0F202C0A0E077E0A0933E01DF +:102CB00087E0870FE72FF0E0E454FC4F10827F5F3E +:102CC0007813F8CF80E090E0FC01E454FC4F1082D0 +:102CD000019687309105C1F71092360210923D019E +:102CE00020E030E00093310210933202209333024F +:102CF00030933402DF91CF911F910F91FF90EF90AD +:102D0000DF90CF90089510923A0280916103811173 +:102D100009C087EB91E00E943D0F8FEB91E00E948C +:102D20003D0F089580913D01882331F064E670E005 +:102D300081E693E00E949B1508952F923F924F9257 +:102D40005F926F927F928F929F92AF92BF92CF923B +:102D5000DF92EF92FF920F931F93CF93DF93CDB744 +:102D6000DEB729970FB6F894DEBF0FBECDBFFE01C8 +:102D70003196CE0108961192E817F907E1F7809194 +:102D80008502909186020DE110E0B8010E94B32AFD +:102D9000FB019B012D5F3F4F8091490490914A04B4 +:102DA000B8010E94B32A6D5F7F4F81E090E002C0BE +:102DB000880F991F6A95E2F7121613063CF4DE019C +:102DC000AE0FBF1F13964C91482B4C932630310504 +:102DD00034F4EC0FFD1F35964081482B4083823040 +:102DE000910564F0E1E0F0E0EC0FFD1FE20FF31F4E +:102DF0006081AC0155954795462B40838034910501 +:102E00000CF0E7C0E1E0F0E0EC0FFD1FE20FF31F74 +:102E1000880F991F9081892B8083DBC0F401ED5AC4 +:102E2000FC4F80819301281B3109C90162E170E0E8 +:102E30000E94B32A462F572F141615060CF4A2C071 +:102E4000ACC0AA2D80E0088519850E1B1F0BEE244F +:102E5000E394F12CEC0EFD1EE00EF11E01E010E0FB +:102E60000C0F1D1F0E0F1F1F873008F07BC077301F +:102E700008F078C0611117C0F8019081F20102C01A +:102E8000F595E795AA95E2F7A92FB0E0AE23BF2309 +:102E9000AB2B29F0E0959E23D8019C9363C0E92BCE +:102EA000D801EC935FC06130C1F4F7019081F20169 +:102EB00002C0F595E795AA95E2F7DF01E92FF0E06A +:102EC000EA23FB23EF2B29F0A0959A23D7019C93AB +:102ED00049C0A92BF701A08345C0623009F5F8016C +:102EE0009081E92FF0E00A2E02C0F595E7950A944B +:102EF000E2F7E0FF0BC0F10102C0EE0FFF1FAA9541 +:102F0000E2F7E0959E23D8019C932CC0F10102C00A +:102F1000EE0FFF1FAA95E2F79E2BF801908322C0C7 +:102F2000633001F5F7019081E92FF0E00A2E02C02D +:102F3000F595E7950A94E2F7E0FF0BC0F10102C0B6 +:102F4000EE0FFF1FAA95E2F7E0959E23D7019C9311 +:102F500009C0F10102C0EE0FFF1FAA95E2F79E2BF8 +:102F6000F70190838F5FA82FB0E0A217B3070CF48E +:102F70007BCF215031097F5FE72FF0E0E417F507A1 +:102F80003CF00BC0262F372FE0E0FB2D70E0682DC2 +:102F9000121613060CF455CFECCFFFEF8F1A9F0AD1 +:102FA00024E08216910409F039CF80916202817089 +:102FB0009091620291FD8F5F823018F00E9483161B +:102FC0001FC040E050E060E0CE0101960E94A00BDF +:102FD00017C0812C912C0F2EF5EF6F2E712CF02D38 +:102FE000B12C06E010E022242394312C6894442470 +:102FF00046F8512CD12CCB2C19870887AD2C0ECF3D +:1030000029960FB6F894DEBF0FBECDBFDF91CF91EA +:103010001F910F91FF90EF90DF90CF90BF90AF90F6 +:103020009F908F907F906F905F904F903F902F90E8 +:103030000895F999FECF92BD81BDF89A80B50895A3 +:10304000009779F020E030E0000000000000000070 +:1030500000000000000000002F5F3F4F8217930721 +:1030600099F708950F931F93CF93DF9300D0CDB7B7 +:10307000DEB78C011A82198289819A8180179107A3 +:1030800070F48EED93E00E94201889819A81019658 +:103090009A83898389819A818017910790F30F9091 +:1030A0000F90DF91CF911F910F910895CF93C6E0BC +:1030B00060E070E082E20E94DA0B8EE190E00E9414 +:1030C000321860E070E083E20E94DA0B8EE190E05B +:1030D0000E943218C15061F760E070E083EC91E02B +:1030E0000E949B1580913D018823E1F3CF910895C3 +:1030F0003F924F925F926F927F928F929F92AF9288 +:10310000BF92CF92DF92EF92FF920F931F93CF93D4 +:10311000DF93CDB7DEB72A970FB6F894DEBF0FBEA8 +:10312000CDBF8091E301813089F030F0823069F1C8 +:10313000833009F45DC04FC24EE161E1809104012A +:103140000E941B0881E08093E30145C210910401B5 +:1031500021E0AE014F5F5F4F61E1812F0E94300897 +:1031600089818E3121F482E08093E30134C21632EA +:1031700031F41092E30182E6809304012CC2109294 +:10318000E30186E28093040126C21091040144E227 +:1031900060E0812F0E941B0881E090E00E943218BD +:1031A0004EE161E1812F0E941B0881E090E00E94C6 +:1031B000321845E060E1812F0E941B0881E090E019 +:1031C0000E94321840E062E1812F0E941B0881E0DA +:1031D00090E00E94321840E06FE0812F0E941B08AF +:1031E00081E090E00E94321883E08093E301F3C114 +:1031F0003090040126E0AE014F5F5F4F62E0832D07 +:103200000E9430080E94BD0780933802EA80F12CAA +:10321000FE2CEE248981E80EF11CF594E794F594D8 +:10322000E794B7010F2C000C880B990B0E9403291F +:103230002B013C01CC80D12CDC2CCC248B81C80E02 +:10324000D11CD594C794D594C794B6010D2C000C0D +:10325000880B990B0E9403294B015C010E8110E041 +:10326000102F00278D81080F111D159507951595B5 +:103270000795B801012E000C880B990B0E940329B9 +:103280006F83788789879A87F0924C04E0924B0489 +:10329000D0925203C09251031093A6030093A5034A +:1032A00020E030E040E859E3C501B4010E94E7297D +:1032B00026E2321209C020E030E044EC52EC0E94D9 +:1032C000E7294B015C0108C020E030E044EC52E407 +:1032D0000E94E7294B015C0120E030E040E859E31F +:1032E000C301B2010E94E72920E030E044EC52E43F +:1032F0000E94E7292B013C0120E030E040E859E33F +:103300006F81788589859A850E94E72920E030E0E1 +:1033100044EC52EC0E94E7296B017C018091E201B0 +:1033200081111CC04092DE015092DF016092E001E9 +:103330007092E1018092DA019092DB01A092DC01AF +:10334000B092DD01C092D601D092D701E092D801AF +:10335000F092D90181E08093E2013BC12DEC3CEC7D +:103360004CEC5DE36091DE017091DF018091E00142 +:103370009091E1010E94E7296F83788789879A8776 +:103380002CEE31E548EB5DE3C301B2010E94E72971 +:103390009B01AC016F81788589859A850E9476278B +:1033A0002CE53FE842E45EE30E9459282B013C01F2 +:1033B0006093DE017093DF018093E0019093E1015F +:1033C0002DEC3CEC4CEC5DE36091DA017091DB019B +:1033D0008091DC019091DD010E94E7296F8378875D +:1033E00089879A872CEE31E548EB5DE3C501B4018E +:1033F0000E94E7299B01AC016F81788589859A85B8 +:103400000E9476272CE53FE842E45EE30E945928BB +:103410004B015C016093DA017093DB018093DC0166 +:103420009093DD012DEC3CEC4CEC5DE36091D6011A +:103430007091D7018091D8019091D9010E94E7291C +:103440006F83788789879A872CEE31E548EB5DE3B7 +:10345000C701B6010E94E7299B01AC016F81788505 +:1034600089859A850E9476272CE53FE842E45EE351 +:103470000E9459286B017C016093D6017093D7019B +:103480008093D8019093D901C301B2010E94CB2847 +:1034900004EC14E0F80171836083C501B4010E945B +:1034A000CB28F80173836283C701B6010E94CB2841 +:1034B000F8017583648301E514E0F8016481758186 +:1034C000072E000C880B990B0E940329A701960177 +:1034D0000E9476270E94CB287093B1036093B003BB +:1034E000F80162817381072E000C880B990B0E94F2 +:1034F0000329A50194010E9476270E94CB2870938E +:103500004A0460934904F80160817181072E000C20 +:10351000880B990B0E940329A30192010E94762730 +:103520000E94CB287093860260938502A7019601C2 +:10353000C701B6010E94E7296F83788789879A8738 +:10354000A5019401C501B4010E94E7299B01AC01CA +:103550006F81788589859A850E9476276F83788721 +:1035600089879A87A7019601C701B6010E94E729BA +:103570006B017C01A5019401C501B4010E94E729FA +:103580009B01AC01C701B6010E9476276B017C014B +:10359000A3019201C301B2010E94E7299B01AC0182 +:1035A000C701B6010E9476270E945A2A20E030E027 +:1035B0004CEB52E40E9475270E94CB289B01772395 +:1035C00024F422273327261B370B3093BB03209389 +:1035D000BA030E94CC132A960FB6F894DEBF0FBE32 +:1035E000CDBFDF91CF911F910F91FF90EF90DF90B2 +:1035F000CF90BF90AF909F908F907F906F905F9093 +:103600004F903F90089540E86AE08DE00E941B08CB +:1036100084E690E00E94201841E06BE08DE00E947B +:103620001B0881E090E00E94321880E00E9464094B +:1036300081E090E00E9432184DE169E08DE00E9447 +:103640001B0881E090E00E94321808954F925F922B +:103650006F927F928F929F92AF92BF92CF92DF92A2 +:10366000EF92FF920F931F93CF93DF93CDB7DEB707 +:103670002E970FB6F894DEBF0FBECDBF80916302C8 +:10368000883F39F00E94031B0E94BD0780936302AC +:1036900076C103E010E01F82188619861A86812CF5 +:1036A000912C540126E0AE014F5F5F4F60E08DE04A +:1036B0000E9430080E94BD07809363024090BD04C1 +:1036C0005090BE046090BF047090C0046A8170E0A6 +:1036D000762F66278981682B072E000C880B990BA3 +:1036E0000E940329A30192010E94E7296B017C013A +:1036F0006093B4037093B5038093B6039093B703BC +:103700006C8170E0762F66278B81682B072E000C6A +:10371000880B990B0E940329A30192010E94E729BB +:103720002B013C0160935B0370935C0380935D030A +:1037300090935E03A7019601C501B4010E9476270C +:103740004B015C01A30192016F81788589859A857F +:103750000E9476276F83788789879A87015011099D +:1037600009F0A0CFB7FAB094B7F8B0948092B40340 +:103770009092B503A092B603B092B7036B017C019F +:10378000F7FAF094F7F8F094C0925B03D0925C03E0 +:10379000E0925D03F0925E0380911C01882321F08A +:1037A0000E941B0910921C010E947608409074022E +:1037B0005090750260907602709077028090780247 +:1037C00090907902A0907A02B0907B02A5019401BA +:1037D0006091B4037091B5038091B6039091B703E3 +:1037E0000E94752720E030E044E354E40E94E7297A +:1037F0006B017C01A5019401C301B2010E947527F0 +:103800009B01AC01C701B6010E94592820E030E0BD +:1038100044EB53E40E9475276B017C016093B40371 +:103820007093B5038093B6039093B70380917002B1 +:1038300090917102A0917202B09173028F83988768 +:10384000A987BA879C01AD0160915B0370915C030D +:1038500080915D0390915E030E94752720E030E027 +:1038600044E354E40E94E7296B877C878D879E8719 +:103870002F81388549855A8560916C0270916D025F +:1038800080916E0290916F020E9475279B01AC019E +:103890006B857C858D859E850E94592820E030E0CF +:1038A00044EB53E40E9475279B01AC0160935B03DA +:1038B00070935C0380935D0390935E03C701B60130 +:1038C0000E94F5276B017C0120E030E0A9010E94F5 +:1038D0005428882354F420ED3FE049EC50E4C7011C +:1038E000B6010E9476276B017C0120ED3FE049EC98 +:1038F00050E4C701B6010E94DA29181654F420EDED +:103900003FE049EC50E4C701B6010E9475276B0106 +:103910007C0120E030E044E353E4C701B6010E949B +:10392000E72920ED3FE049E450E40E94592820E0D7 +:1039300030E04FE753E40E94E72920E030E044EB19 +:1039400053E40E94592820E030E0A9010E94762724 +:103950000E94D228162F6093B30320E030E04AEF94 +:1039600054E4C501B4010E9476279B01AC01C30158 +:10397000B2010E94DA29181614F41093A4032E96AB +:103980000FB6F894DEBF0FBECDBFDF91CF911F9170 +:103990000F91FF90EF90DF90CF90BF90AF909F90EE +:1039A0008F907F906F905F904F9008950E94261B9C +:1039B0000895CF92DF92EF92FF920F931F93CF93D0 +:1039C000DF93CDB7DEB760970FB6F894DEBF0FBEBA +:1039D000CDBF90E1EFE5F1E0DE01119601900D928F +:1039E0009A95E1F78E010F5F1F4F6E0121E1C20E24 +:1039F000D11CE82EF12CF801819191918F010E9448 +:103A0000510D80914101F82FFE9DC001FF9D900D49 +:103A100011240E9432180C151D0569F760960FB627 +:103A2000F894DEBF0FBECDBFDF91CF911F910F91F4 +:103A3000FF90EF90DF90CF900895CF92DF92EF92BA +:103A4000FF920F931F93CF93DF93CDB7DEB72897E5 +:103A50000FB6F894DEBF0FBECDBF98E0EFE6F1E001 +:103A6000DE01119601900D929A95E1F78E010F5F9C +:103A70001F4F6E0129E0C20ED11CE82EF12CF80177 +:103A8000819191918F010E94510D80914101F82FF8 +:103A9000FE9DC001FF9D900D11240E9432180C154F +:103AA0001D0569F728960FB6F894DEBF0FBECDBF8F +:103AB000DF91CF911F910F91FF90EF90DF90CF900A +:103AC00008951F920F920FB60F9211248FB78F7720 +:103AD0008FBFE0E6F0E088E1808388E08083FFCF5D +:103AE000F89415B81BB818B81EB814B81AB817B897 +:103AF0001DB8E8E6F0E0808182608083D99AECE628 +:103B0000F0E080818F608083E1ECF0E08081877657 +:103B1000808383B7817F846083BF10927A00E4E65C +:103B2000F0E080818FEF8083A5E6B0E08C918D631B +:103B30008C938081826080830FB6F894A8958091E1 +:103B40006000886180936000109260000FBE85B7AE +:103B5000806685BF8F7D85BF789483B7816083BF82 +:103B6000889508951F920F920FB60F9211242F93EC +:103B70003F934F935F936F937F938F939F93AF93F5 +:103B8000BF93EF93FF9386E08093B2008091C204CD +:103B90009091C30401969093C3048093C2048091D2 +:103BA0003B0290913C02A0913D02B0913E02AC01DB +:103BB000BD014F5F5F4F6F4F7F4F40933B0250936C +:103BC0003C0260933D0270933E02813C944DA140C3 +:103BD000B10518F00E94701D74C080913B02909155 +:103BE0003C02A0913D02B0913E0282379740A10570 +:103BF000B10550F180913F01811126C0109237022A +:103C000081E080933F011092780210927902109225 +:103C10007A0210927B021092740210927502109236 +:103C20007602109277021092700210927102109236 +:103C300072021092730210926C0210926D02109236 +:103C40006E0210926F023DC080913B0290913C0247 +:103C5000A0913D02B0913E02893B9B40A105B10578 +:103C600080F18091620282FF2CC08091620283FF0A +:103C700028C01092370281E080932D021AB814B840 +:103C80001DB8109278021092790210927A02109266 +:103C90007B021092740210927502109276021092BA +:103CA00077021092700210927102109272021092BA +:103CB000730210926C0210926D0210926E021092BA +:103CC0006F0280912D02882309F477C080916202EF +:103CD00080FD73C08091620281FD6FC0809162029D +:103CE00082FD6BC08091620283FD67C01092370233 +:103CF0000E94701D62C0FC01ED5AFC4F2081273EDE +:103D000078F030916202AB01082E02C0440F551FBB +:103D10000A94E2F7242F209523232093620213C0F4 +:103D2000FC01ED5AFC4F20812C3D68F44091620269 +:103D3000FB01082E02C0EE0FFF1F0A94E2F79F015D +:103D4000242B20936202019686309105A1F6809182 +:103D50004102882399F080915803853530F4809191 +:103D600062028F7D8093620209C0809158038A3677 +:103D700028F0809162028062809362028091420208 +:103D8000882331F09091620280E289278093620259 +:103D9000E0915E02F0E0EE5BFE4F808180668093F2 +:103DA0007C00EAE7F0E08081886C80830E94D90D76 +:103DB0000E94730D0E942C1105C080E090E061E02C +:103DC00070E099CFFF91EF91BF91AF919F918F914B +:103DD0007F916F915F914F913F912F910F900FBE07 +:103DE0000F901F901895CF93DF9380E387B980ECF5 +:103DF00088B996E19AB9C6E0CBB923E024B985B970 +:103E00001DB81EB8E0E6F0E080818861808399E00B +:103E100090831DB8D4E0DEB9E0ECF0E080818260F0 +:103E20008083E8ECF0E0808182608083E1ECF0E068 +:103E3000808188698083E9ECF0E0808180698083FB +:103E400080E18093CC008093C4008FB780688FBFDF +:103E500025BD86EE86BDEEE6F0E080818160808340 +:103E600080E4809380009093810080E090E00E9445 +:103E7000610D1092B000E1EBF0E0808184608083FE +:103E8000E0E7F0E0808181608083C093B20080E64B +:103E900080937C00D0937A000E94B1078AE090E082 +:103EA0000E9432185C988AE090E00E94321880E00C +:103EB00090E0FC01E159FB4F108201968D32910593 +:103EC000C1F789EC90E00E9419188F3F29F460E057 +:103ED00089EC90E00E94931588EC90E00E941918FC +:103EE0008F3F29F460E088EC90E00E94931587EC06 +:103EF00090E00E9419188F3F29F460E087EC90E071 +:103F00000E94931586EC90E00E9419188A3A09F0F5 +:103F100055C084EC90E00E94191890E0982F8827F3 +:103F2000C1E5D4E09D838C8385EC90E00E94191854 +:103F30002C813D81282B3D832C838C819D81019692 +:103F400021F4109256041092550482EC90E00E94E5 +:103F5000191890E0982F8827C1E5D4E09B838A83C5 +:103F600083EC90E00E9419182A813B81282B3B8327 +:103F70002A838A819B81019621F410925404109225 +:103F8000530480EC90E00E94191890E0982F882745 +:103F9000C1E5D4E09983888381EC90E00E941918F0 +:103FA00028813981282B398328838881998101963A +:103FB00069F4109252041092510408C0E1E5F4E053 +:103FC000118210821382128215821482DF91CF91A6 +:103FD0000895CF93C82F80915602909157020E9466 +:103FE000412B0E943C2B6C2F70E00E94B32A8F5F04 +:103FF000CF910895CF92DF92EF92FF920F931F938C +:10400000CF93DF93882309F48EC11092180280E0C9 +:1040100090E0FC01E454FC4F1082FC01E45BFD4F96 +:104020001082019687309105A1F784EF91E090937B +:104030001A01809319018AE090E09093180180930F +:10404000170187E00E94E91F282F30E03093160106 +:104050002093150127E030E03093140120931301E1 +:104060002FEF3FEF30931201209311013093100195 +:1040700020930F0123E030E03093170220931602C3 +:1040800091E090930E01682F660F660F660F681B14 +:10409000695F82E00E948A0966E182E00E948A09E3 +:1040A0006DE182E00E948A09109215021092550279 +:1040B00010925402809118028F5F8093180280E062 +:1040C00090E03AC18091540290915502C09119013B +:1040D000D0911A01C817D90708F0B4C01092550240 +:1040E0001092540200911501109116018091110156 +:1040F000909112019801280F391F2730310544F0A3 +:10410000919581959109909312018093110109C0B5 +:1041100033233CF4919581959109909312018093FA +:104120001101E0901301F090140180910F01909122 +:1041300010019701280F391F283031053CF0919567 +:10414000819591099093100180930F01C0900F0108 +:10415000D0901001C7018C0D9D1D1816190684F012 +:1041600081E080932F0210922E028CE00E94D91CD5 +:104170000E945618109218028091150290E0DCC03F +:104180000297B4F52091110130911201200F311FD7 +:10419000822F880F880F880F821B9E2D9C0D890F00 +:1041A0000E94070A882381F08EEE93E90E94510D48 +:1041B000D194C194D108D0921001C0920F01809186 +:1041C00015028F5F8093150280911701909118015D +:1041D000C81BD90BC233D1052CF0D0931A01C09360 +:1041E000190106C082E390E090931A0180931901AF +:1041F00080910E01882331F1602F660F660F660FE4 +:10420000601B6E0D81E00E948A09809111019091DE +:104210001201080F191F10931601009315016091E8 +:104220000F0170911001E60EF71EF0921401E0925A +:104230001301602F660F660F660F601B6E0D82E024 +:104240000E948A098091620282FF28C08091130235 +:10425000823020F110921302C0911602D091170201 +:104260001C161D060CF044C0CE010196682F660F87 +:10427000660F660F681B6F5F81E00E948A092197B5 +:10428000D0931702C09316026C2F660F660F660F4D +:104290006C1B6F5F82E00E948A092AC080916202D3 +:1042A00083FF26C080911402823010F11092140214 +:1042B000C0911602D0911702C530D105CCF46C2FF5 +:1042C000660F660F660F6C1B6F5F81E00E948A09A4 +:1042D000CE010196909317028093160222966C2FBE +:1042E000660F660F660F6C1B6F5F82E00E948A0983 +:1042F0008091620282FD05C0E3E1F2E080818F5F80 +:1043000080838091620283FD08C0E3E1F2E0818155 +:104310008F5F818380E090E00FC080E090E00CC070 +:1043200080E090E009C080911802882309F46FCEE4 +:10433000813009F4C7CEF4CFDF91CF911F910F9157 +:10434000FF90EF90DF90CF9008950F931F93CF933E +:10435000DF93CDB7DEB727970FB6F894DEBF0FBE59 +:10436000CDBF882309F440C083E080930D01EBE0CA +:10437000F1E081E08083118288E592E090930A0168 +:10438000809309011092120210921102E3E0F2E010 +:10439000A5EFB1E081E192E0119211921D921D9280 +:1043A000E817F907C9F78AE090E090930801809335 +:1043B000070180E090E0FC01E454FC4F1082FC0116 +:1043C000E45BFD4F1082019687309105A1F781E0F3 +:1043D00080932F0286E080932E0280915D0280936D +:1043E000F40100E010E019C18091070190910801EB +:1043F000039708F447C08091090190910A018D321A +:1044000021E0920730F0059790930A01809309010B +:1044100005C0019790930A018093090180910901D9 +:1044200090910A01883C910530F48AEF90E09093D6 +:104430000A018093090110920801109207010BE014 +:1044400011E087E00E94E91F8150F801808391818B +:104450008917B9F380930C01E3E0F2E041E152E007 +:10446000208131813160219331934E175F07C1F76D +:10447000E82FEE0FFF0BED5FFD4F808191819E7F56 +:104480009183808360910D01462F062E000C550B01 +:10449000FA01EE0FFF1FED5FFD4F808191818E7F4E +:1044A00091838083209154023091550280910901BB +:1044B00090910A018217930768F5109255021092A5 +:1044C0005402A3E0B2E021E132E0FD01808191815C +:1044D00096958795819391932E173F07B9F7E5EF4E +:1044E000F1E08D919D91819391932A173B07C9F734 +:1044F00080910701909108010196909308018093A3 +:10450000070180911102909112020196909312027C +:1045100080931102440F551FFA01EB50FE4F80812A +:1045200091818C010170112780FF0FC081E0809381 +:104530002F0210922E028CE00E94D91C0E94561865 +:10454000009111021091120268C08091620282FFF4 +:104550000AC08091F201823030F0615060930D0109 +:104560001092F2010DC08091620283FF09C0809118 +:10457000F301823028F06F5F60930D011092F30118 +:104580008091620282FD05C0E2EFF1E080818F5FE1 +:1045900080838091620283FD05C0E2EFF1E08181BA +:1045A0008F5F818380910D01882324F486E08093BE +:1045B0000D0121C08730FCF010920D011CC08081DC +:1045C00032968D932E173F07D1F740E050E060E020 +:1045D000CE0101960E94A00B80915D029091F401A2 +:1045E0009817D9F08093F40181E080932F0286E040 +:1045F00080932E0212C0E0910D01EE0FFF0BED5FD4 +:10460000FD4F80819181816091838083E3E0F2E0BE +:10461000DE01119621E132E0D2CFC80127960FB614 +:10462000F894DEBF0FBECDBFDF91CF911F910F91E8 +:1046300008951F93CF93DF93CDB7DEB7CB55D10944 +:104640000FB6F894DEBF0FBECDBF9CE1EFE7F1E0FF +:10465000DE01119601900D929A95E1F7FE017D968B +:104660009CE1DF011D929A95E9F790E29E8F99A750 +:1046700092E09CA79FAB9CE1EBE9F1E0DE01D996CB +:1046800001900D929A95E1F7882319F01092F101AB +:1046900007C08091F101882319F0813069F10AC1C6 +:1046A00088E592E0909306018093050184E00E94E2 +:1046B000E91F81508093F0018093EF011092550221 +:1046C00010925402E8EEF1E081E1808381838283DD +:1046D00013828483858386831092E7011092E6011A +:1046E0001092E5018091F1018F5F8093F1011092AA +:1046F000E4018FEF9FEF22C12091540230915502C7 +:1047000080910501909106018217930708F05CC023 +:1047100001978C32B1E09B0728F0909306018093BB +:10472000050106C080E491E09093060180930501A5 +:104730008091E60188232CF08091E5018F5F8093C2 +:10474000E501109255021092540284E00E94E91F84 +:1047500081508093F0019091EF0189130AC084E0A9 +:104760000E94E91F81508093F0019091EF0198170A +:10477000B1F31092E6018093EF0191E09093E40190 +:104780006DE170E06C0F7D1F27E0829F600D711D51 +:104790001124E8EEF1E09E012B5A3F4F4FEE51E01D +:1047A000DB019D91BD018191892BD9018D939D01E3 +:1047B000E417F507A9F740E050E060E0CE018B5A1E +:1047C0009F4F0E94A00B04C08091E601811182C01E +:1047D0002091F001211108C08091620280FF9AC0EF +:1047E00081E18093E601A7C0213041F4809162020B +:1047F00081FF90C081E28093E6019DC0223041F4A8 +:104800008091620282FF86C081E38093E60193C0BB +:10481000233009F07FC08091620283FF7BC081E476 +:104820008093E60188C0DB019D91BD018191892BB8 +:10483000D9018D939D01E417F507A9F740E050E0F9 +:1048400060E0CE018B5A9F4F0E94A00B8CE00E942B +:104850001D1D1E7F10681093E6018091E7018F5F98 +:104860008093E70127C08091E401882319F161E07A +:1048700070E06C0F7D1FB7E02B9F600D711D112440 +:10488000E8EEF1E09E012B5A3F4F4FEE51E0DB0185 +:104890009D91BD018191892BD9018D939D01E417D3 +:1048A000F507A9F740E050E060E0CE018B5A9F4F3A +:1048B0000E94A00B8091E501863048F08CE00E94B8 +:1048C000D91C0E9456188091E70190E037C08FEF05 +:1048D0009FEF34C01091E60110FFECCF812F82953D +:1048E0008F7090E00197DC01AA0FBB1FAA0FBB1FBE +:1048F000AA0FBB1FA81BB90B69E370E06C0F7D1FEB +:104900006A0F7B1FE8EEF1E09E012B5A3F4F4FEEFE +:1049100051E089CF40915402509155028091050198 +:10492000909106019695879596958795841795079A +:1049300008F499CFBFCF1091E601D0CFC55ADF4F11 +:104940000FB6F894DEBF0FBECDBFDF91CF911F91A0 +:104950000895CF93DF93CDB7DEB764970FB6F89481 +:10496000DEBF0FBECDBF109253020E94F31E16E0B1 +:1049700060E070E082E20E94DA0B84E190E00E9445 +:10498000321860E070E083E20E94DA0B84E190E08C +:104990000E943218115061F7412C512CB12CCC24BB +:1049A000C394D12CAA24A3940F2EF3E03F2EF02D14 +:1049B0006894772471F86894222422F80FE614E0B2 +:1049C0007E0185E1E80EF11C14C0B11006C00E9402 +:1049D0007818BA2CC12CD12C0CC0E1E0BE1206C054 +:1049E0000E94D61CB72CC12CD12C03C0B12CC12CD9 +:1049F000D12C80913F01882309F4B3C180914302F7 +:104A000082FF0FC080913F0188235CF080914302B8 +:104A10008B7F8093430280913F01806880933F01A8 +:104A20001CC08091430283FF18C080913F018823FE +:104A3000A4F480914302877F8093430280913F01D9 +:104A40008F7780933F0180913F0191E0980F909381 +:104A50003F01843010F0A0923F0160903F01641448 +:104A600079F08CED9DE90E94510D40903F0180E06E +:104A70000E945A0D80913F01813009F02FC207C07A +:104A800080913F01813069F4511007C1462C0E948A +:104A90009D1680913F018F77843009F413C1512C0A +:104AA00060C180913F01823009F080C0F2E05F1662 +:104AB00039F1F51530F0552071F081E0581699F074 +:104AC000EEC0E4E05E16D9F15E1658F1F5E05F162F +:104AD00009F467C0E4C0462C64E670E082EC91E023 +:104AE0000E949B15F3C180913D01882309F4EDC11B +:104AF00062E370E08BEC91E00E949B15462CCDC1E7 +:104B000080913D01882309F4C7C188EC90E00E94A0 +:104B1000191842E350E060E090E00E94100C462C2F +:104B2000CCC180913D01882309F4C4C184E690E0A2 +:104B30000E9432188A2D0E94A521522CB7C180E014 +:104B40000E94A5214C01892B09F4B0C188EC90E0AA +:104B50000E941918482F940128503109ABEABAEA8B +:104B60000E94CD2A4C0196948794842F90E088155A +:104B7000990528F4682D88EC90E00E9493158091A7 +:104B80003D018823E1F38114910431F042E350E0C8 +:104B900060E0C4010E94100C0F2EF5E05F2EF02D96 +:104BA00085C180913D01811187C180C1462C8091D2 +:104BB0003F01833009F074C082E0581629F1851551 +:104BC00030F0552071F0E1E05E1691F069C0F4E03C +:104BD0005F16C9F15F1640F185E0581609F457C019 +:104BE0005FC064E670E085EC91E00E949B156EC1A9 +:104BF00080913D01882309F469C162E370E08BEC88 +:104C000091E00E949B1549C180913D01882309F4E0 +:104C100044C189EC90E00E94191842E350E060E042 +:104C200090E00E94100C49C180913D01882309F455 +:104C300044C184E690E00E9432188A2D0E94FA1F37 +:104C4000642C522C33C180E00E94FA1F4C01892B46 +:104C500009F42BC189EC90E00E94191890E08815A6 +:104C6000990528F4682D89EC90E00E9493158091B5 +:104C70003D018823E1F342E350E060E0C4010E947B +:104C8000100C642C0F2EF5E05F2EF02D0FC18091DB +:104C90003D01811112C1642C09C1462C01C0462C72 +:104CA00080913F018F77843009F05BC0E1E05E16B0 +:104CB00089F05E1638F0F2E05F16E1F083E05812FA +:104CC00050C026C062E370E088EC91E00E949B1522 +:104CD0005A2C47C080913D018823F1F187EC90E088 +:104CE0000E94191842E350E060E090E00E94100C2E +:104CF000572C37C080913D01882381F184E690E0F4 +:104D00000E94321881E090E00E941923532C29C0A0 +:104D100080E090E00E941923682E882E992EEFEFF4 +:104D20008E169E06E9F087EC90E00E94191890E03C +:104D30008815990528F4662D87EC90E00E9493155C +:104D400080913D018823E1F342E350E060E0C4013B +:104D50000E94100C572C05C05A2C03C0572C01C0C0 +:104D6000532C80915302882309F48BC00E940613B0 +:104D700080913F01882351F060E070E083EC91E086 +:104D80000E949B1580913D018823E1F3F8018289FF +:104D90000E943A1410923F01F8018685678570E001 +:104DA000782B808188237CF48781882334F4AB01BD +:104DB0006A2DC8010E94A00B33C0AB0160E0C8019E +:104DC0000E94A00B2DC0F8018189882321F08189E0 +:104DD0000E94DA0B25C0F8018789882309F1FE01BA +:104DE00031961192EE16FF06E1F7F80187898823C4 +:104DF00099F020E0822F90E0FC01E957FB4F3081D1 +:104E0000E1E0F0E0EC0FFD1FE80FF91F30832F5FAA +:104E1000F8018789281770F3CE0101960E949B152F +:104E2000F8018089807C49F0608980896F73829560 +:104E30008695869583700E948A09F801848981117C +:104E400003C08589882351F0F8018489882334F4CC +:104E50002489858990E0922B0E94510DF801838965 +:104E600088231CF483890E945A0D1092530280E01B +:104E700090E0FC01E159FB4F108201968D329105C3 +:104E8000C1F70E942C0AF5E6CF16D10408F09DCD9B +:104E90008FEFC81AD80AADCD462C80913F018F778D +:104EA000843009F427CF572C5CCF642C80913F01CC +:104EB000462C57CF462C01C0462C80913F018F775E +:104EC000843009F425CF532C4CCF462C80913F01E0 +:104ED0008F77843009F4FECE5A2C43CF80913F0166 +:104EE000823009F4F9CD512C62CE5058BB27AA2745 +:104EF0000E948D270C94A0290E94922938F00E94CC +:104F0000992920F039F49F3F19F426F40C9468296C +:104F10000EF4E095E7FB0C946229E92F0E94B12979 +:104F200058F3BA17620773078407950720F079F4DE +:104F3000A6F50C94D3290EF4E0950B2EBA2FA02DD4 +:104F40000B01B90190010C01CA01A0011124FF2736 +:104F5000591B99F0593F50F4503E68F11A16F04031 +:104F6000A22F232F342F4427585FF3CF4695379530 +:104F70002795A795F0405395C9F77EF41F16BA0BF5 +:104F8000620B730B840BBAF09150A1F0FF0FBB1FA3 +:104F9000661F771F881FC2F70EC0BA0F621F731FEC +:104FA000841F48F4879577956795B795F7959E3F49 +:104FB00008F0B0CF9395880F08F09927EE0F9795DA +:104FC000879508950E94922960F080E891E009F4A5 +:104FD0009EEF0E94992928F040E851E071F45EEFBD +:104FE0000CC00C9468290C94D329E92FE0780E9416 +:104FF000B12940F3092E052AB1F3261737074807D0 +:10500000590738F00E2E07F8E02569F0E025E06436 +:105010000AC0EF6307F8009407FADB01B9019D01AC +:10502000DC01CA01AD01EF930E9470280E94A02903 +:105030000E9425285F91552339F02BED3FE049E48C +:1050400050FD49EC0C9476270895DF93DD27B92FA6 +:10505000BF7740E85FE31616170648075B0718F4AA +:10506000D92F0E94DF299F938F937F936F930E9484 +:105070009A2AE4EDF1E00E946B290E94A0292F9169 +:105080003F914F915F910E94FA29DD2351F0905892 +:10509000A2EA2AED3FE049EC5FE3D0785D270E9469 +:1050A0008D27DF910C94A0290E943E2908F481E00D +:1050B00008950E946D280C94A0290E94992958F007 +:1050C0000E94922940F029F45F3F29F00C94622954 +:1050D00051110C94D4290C9468290E94B12968F3C9 +:1050E0009923B1F3552391F3951B550BBB27AA27A1 +:1050F00062177307840738F09F5F5F4F220F331FDB +:10510000441FAA1FA9F335D00E2E3AF0E0E832D0A2 +:1051100091505040E695001CCAF72BD0FE2F29D0A5 +:10512000660F771F881FBB1F261737074807AB0777 +:10513000B0E809F0BB0B802DBF01FF2793585F4FEC +:105140003AF09E3F510578F00C9462290C94D429D2 +:105150005F3FE4F3983ED4F3869577956795B795CE +:10516000F7959F5FC9F7880F911D9695879597F9D9 +:105170000895E1E0660F771F881FBB1F6217730752 +:105180008407BA0720F0621B730B840BBA0BEE1F67 +:1051900088F7E09508950E94D2286894B1110C9484 +:1051A000D42908950E94B92988F09F5798F0B92F03 +:1051B0009927B751B0F0E1F0660F771F881F991F4C +:1051C0001AF0BA95C9F714C0B13091F00E94D329F2 +:1051D000B1E008950C94D329672F782F8827B85F02 +:1051E00039F0B93FCCF3869577956795B395D9F7A4 +:1051F0003EF490958095709561957F4F8F4F9F4FAE +:105200000895E89409C097FB3EF4909580957095B9 +:1052100061957F4F8F4F9F4F9923A9F0F92F96E902 +:10522000BB279395F695879577956795B795F11177 +:10523000F8CFFAF4BB0F11F460FF1BC06F5F7F4F14 +:105240008F4F9F4F16C0882311F096E911C0772326 +:1052500021F09EE8872F762F05C0662371F096E82F +:10526000862F70E060E02AF09A95660F771F881FFE +:10527000DAF7880F9695879597F90895990F0008A2 +:10528000550FAA0BE0E8FEEF16161706E807F90718 +:10529000C0F012161306E407F50798F0621B730BB3 +:1052A000840B950B39F40A2661F0232B242B252B34 +:1052B00021F408950A2609F4A140A6958FEF811DD7 +:1052C000811D089597F99F6780E870E060E0089578 +:1052D0009FEF80EC0895DF93CF931F930F93FF927E +:1052E000EF92DF927B018C01689406C0DA2EEF0109 +:1052F0000E94FA29FE01E894A591259135914591E6 +:105300005591A6F3EF010E948D27FE019701A80198 +:10531000DA9469F7DF90EF90FF900F911F91CF9192 +:10532000DF91089500240A94161617061806090638 +:10533000089500240A94121613061406050608950B +:10534000092E0394000C11F4882352F0BB0F40F493 +:10535000BF2B11F460FF04C06F5F7F4F8F4F9F4FD3 +:10536000089557FD9058440F551F59F05F3F71F055 +:105370004795880F97FB991F61F09F3F79F08795BC +:105380000895121613061406551FF2CF4695F1DF45 +:1053900008C0161617061806991FF1CF86957105D5 +:1053A000610508940895E894BB2766277727CB0109 +:1053B00097F908950E943E2908F48FEF08959B0104 +:1053C000AC0160E070E080E89FE30C9459280E94F3 +:1053D000FA290C94A0290E94922938F00E94992958 +:1053E00020F0952311F00C9462290C946829112463 +:1053F0000C94D4290E94B12970F3959FC1F3950FA5 +:1054000050E0551F629FF001729FBB27F00DB11D48 +:10541000639FAA27F00DB11DAA1F649F6627B00DD8 +:10542000A11D661F829F2227B00DA11D621F739FC1 +:10543000B00DA11D621F839FA00D611D221F749FCF +:105440003327A00D611D231F849F600D211D822F16 +:10545000762F6A2F11249F5750409AF0F1F088233D +:105460004AF0EE0FFF1FBB1F661F771F881F91506A +:105470005040A9F79E3F510580F00C9462290C948E +:10548000D4295F3FE4F3983ED4F3869577956795EA +:10549000B795F795E7959F5FC1F7FE2B880F911D94 +:1054A0009695879597F9089519F416F40C94682940 +:1054B0000C949E2A0E94B929B8F39923C9F3B6F334 +:1054C0009F57550B87FF0E94AC2A0024A0E640EAB4 +:1054D000900180585695979528F4805C660F771F49 +:1054E000881F20F026173707480730F4621B730B1C +:1054F000840B202931294A2BA6951794079420253F +:1055000031254A2758F7660F771F881F20F0261786 +:105510003707480730F4620B730B840B200D311DE5 +:10552000411DA09581F7B901842F9158880F969558 +:10553000879508959B01AC010C94E7299F3F31F0BA +:10554000915020F4879577956795B795880F911DB1 +:105550009695879597F9089591505040660F771F5B +:10556000881FD2F7089597FB072E16F4009407D0F2 +:1055700077FD09D00E94DC2A07FC05D03EF4909507 +:1055800081959F4F0895709561957F4F0895EE0F17 +:10559000FF1F0590F491E02D0994A29FB001B39FE5 +:1055A000C001A39F700D811D1124911DB29F700D2C +:1055B000811D1124911D0895AA1BBB1B51E107C039 +:1055C000AA1FBB1FA617B70710F0A61BB70B881F93 +:1055D000991F5A95A9F780959095BC01CD01089522 +:1055E0008F929F92AF92BF92CF92DF92EF92FF92F3 +:1055F000CF93DF93EC01688179818A819B8161156A +:1056000071058105910521F464E279ED8BE597E060 +:105610002DE133EF41E050E00E944C2B49015A014B +:105620009B01AC01A7EAB1E40E946B2B6B017C01EA +:10563000ACEEB4EFA50194010E94792BDC01CB0103 +:105640008C0D9D1DAE1DBF1DB7FF03C00197A109A5 +:10565000B04888839983AA83BB839F77DF91CF91DA +:10566000FF90EF90DF90CF90BF90AF909F908F9082 +:1056700008950E94F02A089580E091E00E94F02AA7 +:105680000895A0E0B0E08093000190930101A09301 +:105690000201B09303010895052E97FB1EF40094B8 +:1056A0000E94632B57FD07D00E947E2B07FC03D07E +:1056B0004EF40C94632B50954095309521953F4FB7 +:1056C0004F4F5F4F089590958095709561957F4FEE +:1056D0008F4F9F4F08950E94CD2AA59F900DB49F94 +:1056E000900DA49F800D911D11240895B7FF0C9477 +:1056F0006B2B0E946B2B821B930B0895A1E21A2E39 +:10570000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F65 +:10571000A217B307E407F50720F0A21BB30BE40BB5 +:10572000F50B661F771F881F991F1A9469F76095FC +:105730007095809590959B01AC01BD01CF010895B6 +:04574000F894FFCF0B +:10574400010000002658020A00580201000301FF6C +:10575400FFFFFF040003003200F4010101004000D8 +:105764000000200000008000000400000008000089 +:1057740000000001002000000000080000010201F8 +:105784000104030F020F010F000F070F060FF8B9F2 +:105794003B3435672FBE2CDC278323A31FDC1DDCA1 +:1057A4001DA31F8323DC27BE2C672F3435B93BDCB4 +:1057B4001DB317EE13EE0EEE0EEE13B317DC1D2021 +:1057C40040200000000000000000204020020402ED +:1057D400000000000000000002040240204000001D +:1057E400000000000000402040040204000000000B +:1057F4000000000004020441542B4E414D45000DAD +:105804000A00322000332000342E20482D53434F09 +:0458140052450000F9 +:0400000300003DE6D6 +:00000001FF diff --git a/app/modules/ProboConnect.js b/app/modules/ProboConnect.js index e0938da26..36bd0b2f2 100644 --- a/app/modules/ProboConnect.js +++ b/app/modules/ProboConnect.js @@ -1,350 +1,323 @@ -const BaseModule = require('./baseModule'); - -class ProboConnect extends BaseModule { - constructor() { - super(); - - this.foo = 0; - this.sp = null; - this.EdgeBuff = { - FEA1:0, - FEA2:0, - FEA3:0, - FEA4:0, - REA1:0, - REA2:0, - REA3:0, - REA4:0, - BEA1:0, - BEA2:0, - BEA3:0, - BEA4:0 - }; - this.InputData = { - Analog:{ - AA1: 0, - AA2: 0, - AA3: 0, - AA4: 0 }, - Digital:{ - A1: 0, - A2: 0, - A3: 0, - A4: 0, - FEA1:0, - FEA2:0, - FEA3:0, - FEA4:0, - REA1:0, - REA2:0, - REA3:0, - REA4:0, - BEA1:0, - BEA2:0, - BEA3:0, - BEA4:0 }, - Remote:{ - R_1:0, - R_2:0, - R_3:0, - R_4:0, - R_5:0, - R_6:0, - R_7:0, - R_8:0, - R_L1:0, - R_L2:0, - R_R1:0, - R_R2:0 }, - EEPROM:{ - EC:0, - EEPR2:0, - EEPR1:0 - }, - Infinite:{ - ROTATION_1:0, - ROTATION_2:0, - ROTATION_3:0, - ROTATION_4:0 - }, - Acceler:{ - AXIS_X1:0, - AXIS_X2:0, - AXIS_X3:0, - AXIS_X4:0, - AXIS_Y1:0, - AXIS_Y2:0, - AXIS_Y3:0, - AXIS_Y4:0, - AXIS_Z1:0, - AXIS_Z2:0, - AXIS_Z3:0, - AXIS_Z4:0, - } - - }; - - this.RemoteData = { - B1:0, - B2:0, - B3:0, - B4:0, - Servo1:0, - Servo2:0, - Servo3:0, - Servo4:0, - DC1:0, - DC2:0, - DC3:0, - DC4:0, - MEL2:0, - MEL1:0, - FND:100, - EEPR4:0, - EEPR3:0, - EEPR2:0, - EEPR1:0, - ASET2:0, - ASET1:0 - }; - - // this.Infinite_Buff = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - // this.Infinite_Count = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - // this.Infinite_Start = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - - this.OutputData = new Buffer(22); - - this.OutputData[0] = 0xAD; - this.OutputData[1] = 0xDA; - this.OutputData[2] = 0x00; - this.OutputData[3] = 0x00; - this.OutputData[4] = 0x00; - this.OutputData[5] = 0x00; - this.OutputData[6] = 0x00; - this.OutputData[7] = 0x00; - this.OutputData[8] = 0x00; - this.OutputData[9] = 0x00; - this.OutputData[10] = 0x00; - this.OutputData[11] = 0x00; - this.OutputData[12] = 0x00; - this.OutputData[13] = 0x00; - this.OutputData[14] = 0x00; - this.OutputData[15] = 0x00; - this.OutputData[16] = 0x00; - this.OutputData[17] = 0x00; - this.OutputData[18] = 0x00; - this.OutputData[19] = 0x00; - this.OutputData[20] = 0x00; - this.OutputData[21] = 0x00; - - - } - - // init(handler, config) {} - // - // setSerialPort(sp) { - // this.sp = sp; - // } - - // 연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다. - requestInitialData(sp){ - console.count('InitialData'); - this.sp = sp; - var initTxBuf = new Buffer([0x63, 0x36]); - return initTxBuf; - } - - // 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다. - checkInitialData(data, config) { - console.count('checkInit'); - //const TxBuf = new Buffer([0x1B, 0x00, 0x00, 0x00, 0x0E]); - const TxBuf = new Buffer([0x24, 0x42]); - var rt = false; - - if((data[0]&0x30) == 0x30){ - rt = true; - if((data[0]&0x32) != 0x32) this.sp.write(TxBuf); - } - - return rt; - } - - // optional. 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. - validateLocalData(data) { - return true; - } - - // 엔트리로 전달할 데이터 - requestRemoteData(handler) { - console.count('write soket'); - handler.write("InputData",this.InputData); - } - - // 엔트리에서 받은 데이터에 대한 처리 - handleRemoteData(handler) { - console.count('read soket'); - - //handler.read('DC1'); - Object.keys(this.RemoteData).forEach((port) => { - this.RemoteData[port] = handler.read(port); - }); - - this.OutputData[3] = 0xF0 | (this.RemoteData.B4 << 3) | (this.RemoteData.B3 << 2) | (this.RemoteData.B2 << 1) | this.RemoteData.B1; - this.OutputData[4] = this.RemoteData.Servo1; - this.OutputData[5] = this.RemoteData.Servo2; - this.OutputData[6] = this.RemoteData.Servo3; - this.OutputData[7] = this.RemoteData.Servo4; - this.OutputData[8] = this.RemoteData.DC1; - this.OutputData[9] = this.RemoteData.DC2; - this.OutputData[10] = this.RemoteData.DC3; - this.OutputData[11] = this.RemoteData.DC4; - - this.OutputData[12] = this.RemoteData.MEL2; - this.OutputData[13] = this.RemoteData.MEL1; - this.OutputData[14] = this.RemoteData.FND; - this.OutputData[15] = this.RemoteData.EEPR4; - this.OutputData[16] = this.RemoteData.EEPR3; - this.OutputData[17] = this.RemoteData.EEPR2; - this.OutputData[18] = this.RemoteData.EEPR1; - this.OutputData[19] = this.RemoteData.ASET2; - this.OutputData[20] = this.RemoteData.ASET1; - - - // Object.keys(this.SENSOR_MAP).forEach((port) => { - // this.SENSOR_MAP[port] = handler.read(port); - // }); - // - // const receivedStatusColor = this.STATUS_COLOR_MAP[ - // handler.read('STATUS_COLOR') - // ]; - // if ( - // receivedStatusColor !== undefined && - // this.CURRENT_STATUS_COLOR.COLOR !== receivedStatusColor - // ) { - // this.CURRENT_STATUS_COLOR = { - // COLOR: receivedStatusColor, - // APPLIED: false, - // }; - // } - } - - checkSumMk(buff){ - buff[this.OutputData.length - 1] = 0; - for(var i = 3 ; i < this.OutputData.length - 1 ; i++) - buff[this.OutputData.length - 1] += this.OutputData[i]; - } - - // 하드웨어에 전달할 데이터 - requestLocalData() { - console.count('write hardware'); - // var OutputBuff = [0xAD,0xDA,0x00]; - // const TxBuf = new Buffer([0xAD, 0xDA, 0x00]); - this.OutputData[2] = this.OutputData.length - 3; - this.checkSumMk(this.OutputData); - return this.OutputData; - } - - checkSumCk(buff){ - var ck = 0; - for(var i = 3 ; i < (buff[2] + 2) ; i++ ) - ck += buff[i]; - - return buff[buff[2]+2] == (ck & 0xff) ? true : false; - } - - // 하드웨어에서 온 데이터 처리 - handleLocalData(data) { - console.count('read hardware'); - if(data[0]==0xCD && data[1] == 0xDA) - { - if(this.checkSumCk(data)) { - this.InputData.Analog.AA1 = data[4]; - this.InputData.Analog.AA2 = data[5]; - this.InputData.Analog.AA3 = data[6]; - this.InputData.Analog.AA4 = data[7]; - - this.InputData.Digital.A4 = (data[8] & 0x80) ? 1 : 0; - this.InputData.Digital.A3 = (data[8] & 0x40) ? 1 : 0; - this.InputData.Digital.A2 = (data[8] & 0x20) ? 1 : 0; - this.InputData.Digital.A1 = (data[8] & 0x10) ? 1 : 0; - this.InputData.Digital.FEA4 = (data[8] & 0x08) ? 1 : 0; - this.InputData.Digital.FEA3 = (data[8] & 0x04) ? 1 : 0; - this.InputData.Digital.FEA2 = (data[8] & 0x02) ? 1 : 0; - this.InputData.Digital.FEA1 = (data[8] & 0x01) ? 1 : 0; - - this.InputData.Digital.REA4 = (data[9] & 0x80) ? 1 : 0; - this.InputData.Digital.REA3 = (data[9] & 0x40) ? 1 : 0; - this.InputData.Digital.REA2 = (data[9] & 0x20) ? 1 : 0; - this.InputData.Digital.REA1 = (data[9] & 0x10) ? 1 : 0; - this.InputData.Digital.BEA4 = (data[9] & 0x08) ? 1 : 0; - this.InputData.Digital.BEA3 = (data[9] & 0x04) ? 1 : 0; - this.InputData.Digital.BEA2 = (data[9] & 0x02) ? 1 : 0; - this.InputData.Digital.BEA1 = (data[9] & 0x01) ? 1 : 0; - - this.InputData.Remote.R_3 = (data[10] & 0x80) ? 1 : 0; - this.InputData.Remote.R_2 = (data[10] & 0x40) ? 1 : 0; - this.InputData.Remote.R_4 = (data[10] & 0x20) ? 1 : 0; - this.InputData.Remote.R_1 = (data[10] & 0x10) ? 1 : 0; - - this.InputData.Remote.R_7 = (data[11] & 0x80) ? 1 : 0; - this.InputData.Remote.R_6 = (data[11] & 0x40) ? 1 : 0; - this.InputData.Remote.R_8 = (data[11] & 0x20) ? 1 : 0; - this.InputData.Remote.R_5 = (data[11] & 0x10) ? 1 : 0 - this.InputData.Remote.R_R1 = (data[11] & 0x08) ? 1 : 0; - this.InputData.Remote.R_L1 = (data[11] & 0x04) ? 1 : 0; - this.InputData.Remote.R_R2 = (data[11] & 0x02) ? 1 : 0; - this.InputData.Remote.R_L2 = (data[11] & 0x01) ? 1 : 0; - - this.InputData.EEPROM.EC = data[13]; - this.InputData.EEPROM.EEPR2 = data[14]; - this.InputData.EEPROM.EEPR1 = data[15]; - - this.InputData.Infinite.ROTATION_1 = (data[16]>>6)&0xC; - this.InputData.Infinite.ROTATION_2 = (data[16]>>4)&0xC; - this.InputData.Infinite.ROTATION_3 = (data[16]>>2)&0xC; - this.InputData.Infinite.ROTATION_4 = (data[16]>>0)&0xC; - - this.InputData.Acceler.AXIS_X1 = data[4]; - this.InputData.Acceler.AXIS_X2 = data[5]; - this.InputData.Acceler.AXIS_X3 = data[6]; - this.InputData.Acceler.AXIS_X4 = data[7]; - - this.InputData.Acceler.AXIS_Y1 = data[17]; - this.InputData.Acceler.AXIS_Y2 = data[19]; - this.InputData.Acceler.AXIS_Y3 = data[21]; - this.InputData.Acceler.AXIS_Y4 = data[23]; - - this.InputData.Acceler.AXIS_Z1 = data[18]; - this.InputData.Acceler.AXIS_Z2 = data[20]; - this.InputData.Acceler.AXIS_Z3 = data[22]; - this.InputData.Acceler.AXIS_Z4 = data[24]; - - } - else - console.count('CheckSum Err'); - } - //this.sensors = data; - } - - // // 커스텀 버튼을 사용자에게 보여줄지 여부 - // canShowCustomButton() { - // return true; - // } - - // 커스텀 버튼 클릭시 동작할 로직 - // customButtonClicked(key) { - // switch (key) { - // case "case1": - // //버튼 1 로직 - // break; - // case "case2": - // //버튼 2 로직 - // break; - // default: - // console.log(key); - // } - // } - -} - -module.exports = new ProboConnect(); +const BaseModule = require('./baseModule'); + +class ProboConnect extends BaseModule { + constructor() { + super(); + + this.lastID = 0; + this.foo = 0; + this.sp = null; + this.EdgeBuff = { + FEA1:0, + FEA2:0, + FEA3:0, + FEA4:0, + REA1:0, + REA2:0, + REA3:0, + REA4:0, + BEA1:0, + BEA2:0, + BEA3:0, + BEA4:0 + }; + this.InputData = { + Analog:{ + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + Digital:{ + A1: 0, + A2: 0, + A3: 0, + A4: 0, + FEA1:0, + FEA2:0, + FEA3:0, + FEA4:0, + REA1:0, + REA2:0, + REA3:0, + REA4:0, + BEA1:0, + BEA2:0, + BEA3:0, + BEA4:0 + }, + Remote:{ + R_1:0, + R_2:0, + R_3:0, + R_4:0, + R_5:0, + R_6:0, + R_7:0, + R_8:0, + R_L1:0, + R_L2:0, + R_R1:0, + R_R2:0 + }, + EEPROM:{ + EC:0, + EEPR2:0, + EEPR1:0, + }, + Infinite:{ + ROTATION_1:0, + ROTATION_2:0, + ROTATION_3:0, + ROTATION_4:0 + }, + Acceler:{ + AXIS_X1:0, + AXIS_X2:0, + AXIS_X3:0, + AXIS_X4:0, + AXIS_Y1:0, + AXIS_Y2:0, + AXIS_Y3:0, + AXIS_Y4:0, + AXIS_Z1:0, + AXIS_Z2:0, + AXIS_Z3:0, + AXIS_Z4:0, + } + + }; + + this.RemoteData = { + B1:0, + B2:0, + B3:0, + B4:0, + Servo1:0, + Servo2:0, + Servo3:0, + Servo4:0, + DC1:0, + DC2:0, + DC3:0, + DC4:0, + MEL2:0, + MEL1:0, + FND:100, + EEPR4:0, + EEPR3:0, + EEPR2:0, + EEPR1:0, + ASET2:0, + ASET1:0 + }; + + // this.Infinite_Buff = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, + // this.Infinite_Count = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, + // this.Infinite_Start = { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, + + this.OutputData = new Buffer(22); + + this.OutputData[0] = 0xAD; + this.OutputData[1] = 0xDA; + this.OutputData[2] = 0x00; + this.OutputData[3] = 0x00; + this.OutputData[4] = 0x00; + this.OutputData[5] = 0x00; + this.OutputData[6] = 0x00; + this.OutputData[7] = 0x00; + this.OutputData[8] = 0x00; + this.OutputData[9] = 0x00; + this.OutputData[10] = 0x00; + this.OutputData[11] = 0x00; + this.OutputData[12] = 0x00; + this.OutputData[13] = 0x00; + this.OutputData[14] = 0x00; + this.OutputData[15] = 0x00; + this.OutputData[16] = 0x00; + this.OutputData[17] = 0x00; + this.OutputData[18] = 0x00; + this.OutputData[19] = 0x00; + this.OutputData[20] = 0x00; + this.OutputData[21] = 0x00; + } + + // init(handler, config) {} + // + // setSerialPort(sp) { + // this.sp = sp; + // } + + // 연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다. + requestInitialData(sp){ + this.sp = sp; + var initTxBuf = new Buffer([0x63, 0x36]); + return initTxBuf; + } + + // 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다. + checkInitialData(data, config) { + const TxBuf = new Buffer([0x24, 0x42]); + var rt = false; + + if((data[0]&0x30) == 0x30){ + rt = true; + if((data[0]&0x32) != 0x32) this.sp.write(TxBuf); + } + + return rt; + } + + // optional. 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. + validateLocalData(data) { + return true; + } + + // 엔트리로 전달할 데이터 + requestRemoteData(handler) { + handler.write("InputData",this.InputData); + } + + // 엔트리에서 받은 데이터에 대한 처리 + handleRemoteData(handler) { + Object.keys(this.RemoteData).forEach((port) => { + this.RemoteData[port] = handler.read(port); + }); + this.OutputData[3] = 0xF0 | (this.RemoteData.B4 << 3) | (this.RemoteData.B3 << 2) | (this.RemoteData.B2 << 1) | this.RemoteData.B1; + this.OutputData[4] = this.RemoteData.Servo1; + this.OutputData[5] = this.RemoteData.Servo2; + this.OutputData[6] = this.RemoteData.Servo3; + this.OutputData[7] = this.RemoteData.Servo4; + this.OutputData[8] = this.RemoteData.DC1; + this.OutputData[9] = this.RemoteData.DC2; + this.OutputData[10] = this.RemoteData.DC3; + this.OutputData[11] = this.RemoteData.DC4; + + this.OutputData[12] = this.RemoteData.MEL2; + this.OutputData[13] = this.RemoteData.MEL1; + this.OutputData[14] = this.RemoteData.FND; + this.OutputData[15] = this.RemoteData.EEPR4; + this.OutputData[16] = this.RemoteData.EEPR3; + this.OutputData[17] = this.RemoteData.EEPR2; + this.OutputData[18] = this.RemoteData.EEPR1; + this.OutputData[19] = this.RemoteData.ASET2; + this.OutputData[20] = this.RemoteData.ASET1; + } + + checkSumMk(buff){ + buff[this.OutputData.length - 1] = 0; + for(var i = 3 ; i < this.OutputData.length - 1 ; i++) { + buff[this.OutputData.length - 1] += this.OutputData[i]; + } + } + + // 하드웨어에 전달할 데이터 + requestLocalData() { + this.OutputData[2] = this.OutputData.length - 3; + this.checkSumMk(this.OutputData); + //console.log(this.InputData.EEPROM.ADDRESS, send); + return this.OutputData; + } + + checkSumCk(buff){ + var ck = 0; + for(var i = 3 ; i < (buff[2] + 2) ; i++ ) { + ck += buff[i]; + } + + return buff[buff[2]+2] == (ck & 0xff) + ? true + : false; + } + + // 하드웨어에서 온 데이터 처리 + handleLocalData(data) { + if(data[0]==0xCD && data[1] == 0xDA) + { + if(this.checkSumCk(data)) { + this.InputData.Analog.AA1 = data[4]; + this.InputData.Analog.AA2 = data[5]; + this.InputData.Analog.AA3 = data[6]; + this.InputData.Analog.AA4 = data[7]; + + this.InputData.Digital.A4 = (data[8] & 0x80) ? 1 : 0; + this.InputData.Digital.A3 = (data[8] & 0x40) ? 1 : 0; + this.InputData.Digital.A2 = (data[8] & 0x20) ? 1 : 0; + this.InputData.Digital.A1 = (data[8] & 0x10) ? 1 : 0; + this.InputData.Digital.FEA4 = (data[8] & 0x08) ? 1 : 0; + this.InputData.Digital.FEA3 = (data[8] & 0x04) ? 1 : 0; + this.InputData.Digital.FEA2 = (data[8] & 0x02) ? 1 : 0; + this.InputData.Digital.FEA1 = (data[8] & 0x01) ? 1 : 0; + + this.InputData.Digital.REA4 = (data[9] & 0x80) ? 1 : 0; + this.InputData.Digital.REA3 = (data[9] & 0x40) ? 1 : 0; + this.InputData.Digital.REA2 = (data[9] & 0x20) ? 1 : 0; + this.InputData.Digital.REA1 = (data[9] & 0x10) ? 1 : 0; + this.InputData.Digital.BEA4 = (data[9] & 0x08) ? 1 : 0; + this.InputData.Digital.BEA3 = (data[9] & 0x04) ? 1 : 0; + this.InputData.Digital.BEA2 = (data[9] & 0x02) ? 1 : 0; + this.InputData.Digital.BEA1 = (data[9] & 0x01) ? 1 : 0; + + this.InputData.Remote.R_3 = (data[10] & 0x80) ? 1 : 0; + this.InputData.Remote.R_2 = (data[10] & 0x40) ? 1 : 0; + this.InputData.Remote.R_4 = (data[10] & 0x20) ? 1 : 0; + this.InputData.Remote.R_1 = (data[10] & 0x10) ? 1 : 0; + + this.InputData.Remote.R_7 = (data[11] & 0x80) ? 1 : 0; + this.InputData.Remote.R_6 = (data[11] & 0x40) ? 1 : 0; + this.InputData.Remote.R_8 = (data[11] & 0x20) ? 1 : 0; + this.InputData.Remote.R_5 = (data[11] & 0x10) ? 1 : 0 + this.InputData.Remote.R_R1 = (data[11] & 0x08) ? 1 : 0; + this.InputData.Remote.R_L1 = (data[11] & 0x04) ? 1 : 0; + this.InputData.Remote.R_R2 = (data[11] & 0x02) ? 1 : 0; + this.InputData.Remote.R_L2 = (data[11] & 0x01) ? 1 : 0; + + this.InputData.EEPROM.EC = data[13]; + this.InputData.EEPROM.EEPR2 = data[14]; + this.InputData.EEPROM.EEPR1 = data[15]; + + this.InputData.Infinite.ROTATION_1 = (data[16]>>6)&0xC; + this.InputData.Infinite.ROTATION_2 = (data[16]>>4)&0xC; + this.InputData.Infinite.ROTATION_3 = (data[16]>>2)&0xC; + this.InputData.Infinite.ROTATION_4 = (data[16]>>0)&0xC; + + this.InputData.Acceler.AXIS_X1 = data[4]; + this.InputData.Acceler.AXIS_X2 = data[5]; + this.InputData.Acceler.AXIS_X3 = data[6]; + this.InputData.Acceler.AXIS_X4 = data[7]; + + this.InputData.Acceler.AXIS_Y1 = data[17]; + this.InputData.Acceler.AXIS_Y2 = data[19]; + this.InputData.Acceler.AXIS_Y3 = data[21]; + this.InputData.Acceler.AXIS_Y4 = data[23]; + + this.InputData.Acceler.AXIS_Z1 = data[18]; + this.InputData.Acceler.AXIS_Z2 = data[20]; + this.InputData.Acceler.AXIS_Z3 = data[22]; + this.InputData.Acceler.AXIS_Z4 = data[24]; + } + } + } + + // // 커스텀 버튼을 사용자에게 보여줄지 여부 + // canShowCustomButton() { + // return true; + // } + + // 커스텀 버튼 클릭시 동작할 로직 + // customButtonClicked(key) { + // switch (key) { + // case "case1": + // //버튼 1 로직 + // break; + // case "case2": + // //버튼 2 로직 + // break; + // default: + // console.log(key); + // } + // } + +} + +module.exports = new ProboConnect(); diff --git a/app/modules/alux_nemo.js b/app/modules/alux_nemo.js new file mode 100644 index 000000000..51c946624 --- /dev/null +++ b/app/modules/alux_nemo.js @@ -0,0 +1,727 @@ +function Module() { + this.soundKeyArray = [30578, 28861, 27241, 25713, 24270, 22908, 21622, 20408, 19263, 18182, 17161, 16198]; + this.ledPixelArray = [0, 0, 0, 0, 0, 0, 0]; + this.protocol = { + nemoId: 0x24, + fwVersion: 0x42, + sCmd0 : 0xAD, + sCmd1: 0xDA, + rCmd0: 0xCD, + rCmd1: 0xDA + }; + this.sAddr = { + cmd0: 0, + cmd1: 1, + size: 2, + led7x1: 3, + led7x2: 4, + led7x3: 5, + led7x4: 6, + led7x5: 7, + led7x6: 8, + led7x7: 9, + led7x8: 10, + led7x9: 11, + led7x10: 12, + led7x11: 13, + led7x12: 14, + led7x13: 15, + led7x14: 16, + ledMs0: 17, + ledMs1: 18, + ledPixel: 19, + ledSet: 20, + portSet: 21, + melody: 22, + buzzer0: 23, + buzzer1: 24, + ledRead: 25, + textSize: 0 // 텍스트 크기는 따로 계산하여 입력한다. + }; + this.rAddr = { + cmd0: 0, + cmd1: 1, + size: 2, + accelAx0: 3, + accelAx1: 4, + accelAy0: 5, + accelAy1: 6, + accelAz0: 7, + accelAz1: 8, + accelALinear: 9, + accelD: 10, + illumi: 11, + exPort: 12, + exDigital: 13, + anSwitch0: 14, + anSwitch1: 15, + anSwitch2: 16, + anSwitch3: 17, + diSwitch0: 18, + diSwitch1: 19, + ledRead: 20, + compass: 21, + timeCheck: 22, + cs: 23 + }; + this.length = { + version: 2, + send: 26, // cs 제외 길이 + }; + this.event = { + button: false, + motion: false + }; + this.device = { + fwVersion: 0, + accelA: [0, 0, 0, 0], // x, y, z, linear + accelD: [false, false, false, false, false, false, false, false], // 앞, 뒤, 좌, 우, 위, 아래, 세움, 충격 + illumi: 0, + exPort: 0, + exDigital: [false, false, false, false], // a1, fea1, rea1, bea1 + anSwitch: [0, 0, 0, 0], + diSwitch: { + a: [false, false, false, false], // sw1, sw2, sw3, sw4 + fea: [false, false, false, false], + rea: [false, false, false, false], + bea: [false, false, false, false], + }, + ledRead: { + last: 0, + curr: 0, + state: false, + }, + compass: 0, + timeCheck: [0, 0, 0], + }; + this.deviceEx = { + button: [ + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + } + ], + expansion: { + last: 0, + curr: 0, + start: 0, + state: [0, 0, 0, 0] // 값, 각도, 절대각도, 회전 수 + }, + compass: { + last: 0, + curr: 0, + start: 0, + state: [0, 0, 0, 0, 0] // 값, 각도, 절대각도, 회전 수, 방향 + }, + timeCheck: [ + { + last: 0, + curr: 0, + state: false, + }, + { + last: 0, + curr: 0, + state: false, + }, + { + last: 0, + curr: 0, + state: false, + }, + ] + }; + this.basicBuffer = new Buffer(26); // cs 제외 길이 + this.textBuffer = new Buffer(0); + + this.lastInitBlockId = 0; + this.lastOutputBlockId = 0; + this.lastExtensionBlockId = 0; +}; + +// 최초에 커넥션이 이루어진 후의 초기 설정. +// handler 는 워크스페이스와 통신하 데이터를 json 화 하는 오브젝트입니다. (datahandler/json 참고) +// config 은 module.json 오브젝트입니다. +Module.prototype.init = function(handler, config) { + this.setDefault(); +}; + +// 연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다. +// requestInitialData 를 사용한 경우 checkInitialData 가 필수입니다. +// 이 두 함수가 정의되어있어야 로직이 동작합니다. 필요없으면 작성하지 않아도 됩니다. +Module.prototype.requestInitialData = function() { + const packet = new Buffer(this.length.version); + packet[this.sAddr.cmd0] = this.protocol.nemoId; + packet[this.sAddr.cmd1] = this.protocol.fwVersion; + return packet; +}; + +// 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다. +Module.prototype.checkInitialData = function(data, config) { + let isConnected = false; + if (data.length === this.length.version && data[this.rAddr.cmd0] === this.protocol.fwVersion) { + this.device.fwVersion = data[this.rAddr.cmd1]; + isConnected = true; + } + return isConnected; +}; + +// 하드웨어 기기에 전달할 데이터를 반환합니다. +// slave 모드인 경우 duration 속성 간격으로 지속적으로 기기에 요청을 보냅니다. +Module.prototype.requestLocalData = function() { + const basicSize = this.basicBuffer.length; // cs 제외 길이 + const textSize = this.textBuffer.length; + const packetSize = basicSize + textSize + 1; + const csIndex = packetSize - 1; + const packet = new Buffer(packetSize); + + + this.basicBuffer[0] = this.protocol.sCmd0; + this.basicBuffer[1] = this.protocol.sCmd1; + this.basicBuffer[2] = (packetSize - 3); // cmd와 size 길이 제외 + for (let i = 0; i < basicSize; i++) { + packet[i] = this.basicBuffer[i]; + if (i > this.sAddr.size) { + packet[csIndex] = (packet[csIndex] + packet[i]) & 0xFF; + } + } + if (textSize > 0) { + for (let i = 0; i < textSize; i++) { + const index = basicSize + i; + packet[index] = this.textBuffer[i]; + packet[csIndex] = (packet[csIndex] + packet[index]) & 0xFF; + } + } + + this.basicBuffer = new Buffer(this.length.send); + this.textBuffer = new Buffer(0); + return packet; +}; + +// 주기적으로 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. +Module.prototype.validateLocalData = function(data) { + const size = data.length; + let validation = false; + if (size === this.length.version) { + if (data[this.rAddr.cmd0] === this.protocol.fwVersion) { + validation = true; + this.device.fwVersion = data[this.rAddr.cmd1]; + } + } else { + if (data[this.rAddr.cmd0] === this.protocol.rCmd0 && data[this.rAddr.cmd1] === this.protocol.rCmd1) { + const dataLength = data[this.rAddr.size] - 1; + let cs = 0; + for (let i = 0; i < dataLength; i++) { + cs = ((cs & 0xFF) + data[i + 3]) & 0xFF; + } + if (data[this.rAddr.cs] === cs) { + validation = true; + } + } + } + return validation; +}; + +// 하드웨어에서 온 데이터 처리 +Module.prototype.handleLocalData = function(data) { + const size = data.length + if (size > this.length.version) { + this.parsingAccelA(data); + this.parsingAccelD(data); + this.parsingIllumination(data); + this.parsingExPort(data); + this.parsingExDigital(data); + this.parsingAnSwitch(data); + this.parsingDiSwitch(data); + this.parsingLedRead(data); + this.parsingCompass(data); + this.parsingTimeCheck(data); + } else if (size === this.length.version) { + this.device.fwVersion = data[this.rAddr.cmd1]; + } +}; + +// 엔트리로 전달할 데이터 +Module.prototype.requestRemoteData = function(handler) { + handler.write('NEMO_DEVICE', this.device); + handler.write('NEMO_DEVICE_EX', this.deviceEx); + handler.write('NEMO_EVENT_MOTION', this.event.motion); + handler.write('NEMO_EVENT_BUTTON', this.event.button); + this.event.motion = false; + this.event.button = false; + +}; + +// 엔트리에서 받은 데이터에 대한 처리 +Module.prototype.handleRemoteData = function(handler) { + const init = handler.read('NEMO_INIT'); + const output = handler.read('NEMO_OUTPUT'); + const extension = handler.read('NEMO_EXTENSION'); + + if (init.id !== this.lastInitBlockId) { + this.lastInitBlockId = init.id; + this.setDefault(); + this.addLedClear(true); + this.addMelody(0); + } + + if (output.id !== this.lastOutputBlockId) { + this.lastOutputBlockId = output.id; + switch (output.index) { + case 0: + this.addLedSet(output.iconLED.index, output.iconLED.time); + break; + case 1: + this.addLedLine(output.customLED.icon, output.customLED.value, output.customLED.time); + break; + case 2: + this.addText(output.textLED.text, output.textLED.time); + break; + case 3: + this.addLedClear(output.deleteLED.value); + break; + case 4: + this.addLedPixel(output.coordinateLED.index, output.coordinateLED.state); + break; + case 5: + case 6: + this.addMelody(output.playMelody.title); + break; + case 7: + this.addBuzzer(output.playNote.pitch); + break; + case 9: + this.addBuzzer(output.playNote.pitch); + this.addMelody(output.playMelody.title); + break; + case 10: + this.addLEDRead(output.readLED.index); + break; + + } + } + + if (extension.id !== this.lastExtensionBlockId) { + this.lastExtensionBlockId = extension.id; + switch (extension.index) + { + case 0: + this.addSetExpension(extension.setExpansion.type); + break; + case 1: + this.addSetExpensionValue(extension.setExpansionValue.value); + break; + case 2: + this.addSetCompassValue(extension.setCompassValue.value); + break; + } + } +}; + +// 하드웨어 연결 해제 시 호출 +Module.prototype.disconnect = function(connect) { + connect.close(); +}; + +// 연결 종료 후 처리 코드 +Module.prototype.reset = function() { + +}; + +Module.prototype.setDefault = function() { + this.ledPixelArray = [0, 0, 0, 0, 0, 0, 0]; + this.event = { + button: false, + motion: false + }; + this.device = { + fwVersion: 0, + accelA: [0, 0, 0, 0], // x, y, z, linear + accelD: [false, false, false, false, false, false, false, false], // 앞, 뒤, 좌, 우, 위, 아래, 세움, 충격 + illumi: 0, + exPort: 0, + exDigital: [false, false, false, false], // a1, fea1, rea1, bea1 + anSwitch: [0, 0, 0, 0], + diSwitch: { + a: [false, false, false, false], // sw1, sw2, sw3, sw4 + fea: [false, false, false, false], + rea: [false, false, false, false], + bea: [false, false, false, false], + }, + ledRead: { + last: 0, + curr: 0, + state: false, + }, + compass: 0, + timeCheck: [0, 0, 0], + }; + this.deviceEx = { + button: [ + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + { + last: false, + curr: false, + state: [false, false, false] // 눌려있을 때, 눌렀을 때, 뗐을 때 + } + ], + expansion: { + last: 0, + curr: 0, + start: 0, + state: [0, 0, 0, 0, false, false, false] // 값, 각도, 절대각도, 회전 수, 눌려있을 때, 눌렀을 때, 뗐을 때 + }, + compass: { + last: 0, + curr: 0, + start: 0, + state: [0, 0, 0, 0, 0] // 값, 각도, 절대각도, 회전 수, 방향 + }, + timeCheck: [ + { + last: 0, + curr: 0, + state: false, + }, + { + last: 0, + curr: 0, + state: false, + }, + { + last: 0, + curr: 0, + state: false, + }, + ] + }; + this.basicBuffer = new Buffer(26); // cs 제외 길이 + this.textBuffer = new Buffer(0); +}; + +Module.prototype.parsingAccelA = function(data) { + for (let i = 0; i < 3; i++) { + const lowData = data[i * 2 + 3]; + const highData = data[i * 2 + 4]; + const temp = (lowData & 0x80) === 0x80 + ? (0x10000 - ((lowData << 8) | highData)) * -1 + : (lowData << 8) | highData; + this.device.accelA[i] = temp / 10.0; + } + this.device.accelA[3] = data[this.rAddr.accelALinear] +}; + +Module.prototype.parsingAccelD = function(data) { + for (let i = 0; i < 8; i++) { + const temp = (data[this.rAddr.accelD] >> i) & 0x01; + if (temp === 1) { + this.event.motion = true; + this.device.accelD[7 - i] = true; + } else { + this.device.accelD[7 - i] = false; + } + } +} + +Module.prototype.parsingIllumination = function(data) { + this.device.illumi = data[this.rAddr.illumi]; +} + +Module.prototype.parsingExPort = function(data) { + const sen = data[this.rAddr.exPort]; + this.device.exPort = sen; + this.deviceEx.expansion.curr = sen; + + if (this.deviceEx.expansion.curr !== this.deviceEx.expansion.last) { + let diff = this.deviceEx.expansion.last - this.deviceEx.expansion.curr; + + // 회전수: 3 + if (diff > 200) { + this.deviceEx.expansion.state[3] += 1; + } else if (diff < -200) { + this.deviceEx.expansion.state[3] -= 1; + } + + // 값: 0 + this.deviceEx.expansion.state[0] = (sen - this.deviceEx.expansion.start) + (this.deviceEx.expansion.state[3] * 255); + + // 각도: 1 + let angle = (this.deviceEx.expansion.state[0] % 255); + if (angle < 0) { + angle = 255 + angle; + } + this.deviceEx.expansion.state[1] = Math.floor(angle * 1.41732); + + // 절대각도: 2 + this.deviceEx.expansion.state[2] = Math.floor(sen * 1.41732); + } + + this.deviceEx.expansion.last = this.deviceEx.expansion.curr; +} + +Module.prototype.parsingExDigital = function(data) { + for (let i = 4; i < 8; i++) { + const temp = (data[[this.rAddr.exDigital]] >> i) & 0x01; + this.device.exDigital[i - 4] = temp === 1 ? true : false; + } + // 확장센서 버튼 상태값 + this.deviceEx.expansion.state[4] = this.device.exDigital[3]; + this.deviceEx.expansion.state[5] = this.device.exDigital[2]; + this.deviceEx.expansion.state[6] = this.device.exDigital[1]; +} + +Module.prototype.parsingAnSwitch = function(data) { + this.device.anSwitch[0] = data[this.rAddr.anSwitch0]; + this.device.anSwitch[1] = data[this.rAddr.anSwitch1]; + this.device.anSwitch[2] = data[this.rAddr.anSwitch2]; + this.device.anSwitch[3] = data[this.rAddr.anSwitch3]; +} + +Module.prototype.parsingDiSwitch = function(data) { + for (let i = 0; i < 8; i++) { + const temp1 = ((data[this.rAddr.diSwitch0] >> i) & 0x01) === 1 + ? true + : false; + const temp2 = ((data[this.rAddr.diSwitch1] >> i) & 0x01) === 1 + ? true + : false; + if (4 <= i && i <= 7) { + const index = i - 4; + this.device.diSwitch.a[index] = temp1; + this.deviceEx.button[index].curr = temp1; + this.device.diSwitch.rea[index] = temp2; + + if (!this.deviceEx.button[index].curr && !this.deviceEx.button[index].last) { + this.deviceEx.button[index].state[0] = false; + this.deviceEx.button[index].state[1] = false; + this.deviceEx.button[index].state[2] = false; + } else { + this.event.button = true; + this.deviceEx.button[index].state[0] = true; + if (this.deviceEx.button[index].curr && this.deviceEx.button[index].last) { + this.deviceEx.button[index].state[1] = false; + this.deviceEx.button[index].state[2] = false; + } else if (this.deviceEx.button[index].curr && !this.deviceEx.button[index].last) { + this.deviceEx.button[index].state[1] = true; + this.deviceEx.button[index].state[2] = false; + } else if (!this.deviceEx.button[index].curr && this.deviceEx.button[index].last) { + this.deviceEx.button[index].state[1] = false; + this.deviceEx.button[index].state[2] = true; + } + } + this.deviceEx.button[index].last = this.deviceEx.button[index].curr; + } else if (0 <= i && i <= 3) { + const index = 3 - i; + this.device.diSwitch.fea[index] = temp1; + this.device.diSwitch.bea[index] = temp2; + } + } +}; + +Module.prototype.parsingLedRead = function(data) { + this.device.ledRead.curr = data[this.rAddr.ledRead] & 0x7F; + if (this.device.ledRead.curr !== this.device.ledRead.last) { + this.device.ledRead.state = (data[this.rAddr.ledRead] >> 7) & 0x01; + } + this.device.ledRead.last = this.device.ledRead.curr; +}; + +Module.prototype.parsingCompass = function(data) { + const sen = data[this.rAddr.compass]; + this.device.compass = sen; + this.deviceEx.compass.curr = sen; + + if (this.deviceEx.compass.curr !== this.deviceEx.compass.last) { + let diff = this.deviceEx.compass.last - this.deviceEx.compass.curr; + + // 회전수: 3 + if (diff > 200) { + this.deviceEx.compass.state[3] += 1; + } else if (diff < -200) { + this.deviceEx.compass.state[3] -= 1; + } + + // 값: 0 + this.deviceEx.compass.state[0] = (sen - this.deviceEx.compass.start) + (this.deviceEx.compass.state[3] * 255); + + // 각도: 1 + let angle = (this.deviceEx.compass.state[0] % 255); + if (angle < 0) { + angle = 255 + angle; + } + this.deviceEx.compass.state[1] = Math.floor(angle * 1.41732); + + // 절대각도: 2 + this.deviceEx.compass.state[2] = Math.floor(sen * 1.41732); + + // 방향: 4 + if (35 <= sen && sen < 99) { + this.deviceEx.compass.state[4] = 0; // 동 + } else if (99 <= sen && sen < 163) { + this.deviceEx.compass.state[4] = 2; // 남 + } else if (163 <= sen && sen < 227) { + this.deviceEx.compass.state[4] = 1; // 서 + } else { // 227-34 + this.deviceEx.compass.state[4] = 3; // 북 + } + } + + this.deviceEx.compass.last = this.deviceEx.compass.curr; +}; + +Module.prototype.parsingTimeCheck = function(data) { + for (let i = 0; i < 3; i++) { + this.device.timeCheck[i] = (data[this.rAddr.timeCheck] >> ((3 - i) * 2)) & 0x03; + this.deviceEx.timeCheck[i].curr = this.device.timeCheck[i]; + this.deviceEx.timeCheck[i].state = (this.deviceEx.timeCheck[i].last !== this.deviceEx.timeCheck[i].curr) + ? true + : false; + this.deviceEx.timeCheck[i].last = this.deviceEx.timeCheck[i].curr; + } +}; + +Module.prototype.addLedLine = function(index, led, time) { + // 펌웨어의 x,y 좌표와 실제 표기할 x,y 좌표가 달라 아래와 같이 프로그래밍합니다 + for (let i = 0; i < 7; i++) { + const bitValue = led[i] & 0x01; + this.ledPixelArray[i] |= 0x80; + if (bitValue) { + this.ledPixelArray[i] |= 1 << index; + } else { + this.ledPixelArray[i] &= ~(1 << index); + } + } + for (let i = 0; i < 7; i++) { + this.basicBuffer[this.sAddr.led7x1 + i] = this.ledPixelArray[i]; + } + this.basicBuffer[this.sAddr.ledMs0] = (time >> 8) & 0x7F; + this.basicBuffer[this.sAddr.ledMs1] = time & 0xFF; +}; + +Module.prototype.addLedClear = function(value) { + if (value === true) { + for (let i = 0; i < 7; i++) { + this.basicBuffer[this.sAddr.led7x1 + i] = 0x80; + } + } +} + +Module.prototype.addLedPixel = function(index, state) { + this.basicBuffer[this.sAddr.ledPixel] = ((state & 0x03) << 6) | (index & 0x3F); +}; + +Module.prototype.addLedSet = function(index, time) { + this.basicBuffer[this.sAddr.ledSet] = index; + this.basicBuffer[this.sAddr.ledMs0] = (time >> 8) & 0x7F; + this.basicBuffer[this.sAddr.ledMs1] = time & 0xFF; +}; + +Module.prototype.addPortset = function(index) { + this.basicBuffer[this.sAddr.portSet] = index & 0x0F; +}; + +Module.prototype.addMelody = function(index) { + this.basicBuffer[this.sAddr.melody] = 0x80 | (index & 0x7F); +}; + +Module.prototype.addBuzzer = function(note) { + if (0 <= note && note <= 47) { + const n = (note / 12) & 0xFF; + const v = note % 12; + let r = 2; + for (let i = 0; i < n; i++) { + r *= 2; + } + const hertz = this.soundKeyArray[v] / r; + this.basicBuffer[this.sAddr.buzzer0] = 0x80 | ((hertz >> 8) & 0x7F); + this.basicBuffer[this.sAddr.buzzer1] = hertz & 0x7F; + } +}; + +Module.prototype.addText = function(text, time) { + const size = text.length; + this.textBuffer = new Buffer(size + 1); + this.textBuffer[this.sAddr.textSize] = size; + for (let i = 0; i < size; i++) { + this.textBuffer[i + 1] = text[i].charCodeAt(); + } + this.basicBuffer[this.sAddr.ledMs0] = (time >> 8) & 0x7F; + this.basicBuffer[this.sAddr.ledMs1] = time & 0xFF; +}; + +Module.prototype.addLEDRead = function(index) { + this.basicBuffer[this.sAddr.ledRead] = index; +}; + +Module.prototype.addSetExpension = function(type) { + switch (type) { + case 1: + case 2: + case 3: + this.basicBuffer[this.sAddr.portSet] = 0x01; + break; + case 4: + case 6: + this.basicBuffer[this.sAddr.portSet] = 0x02; + break; + case 5: + this.basicBuffer[this.sAddr.portSet] = 0x07; + break; + case 7: + this.basicBuffer[this.sAddr.portSet] = 0x08; + break; + case 8: + this.basicBuffer[this.sAddr.portSet] = 0x04; + break; + case 9: + this.basicBuffer[this.sAddr.portSet] = 0x05; + break; + case 10: + this.basicBuffer[this.sAddr.portSet] = 0x06; + break; + } +}; + +Module.prototype.addSetExpensionValue = function(value) { + this.deviceEx.expansion.start = this.device.exPort - (value % 255); + this.deviceEx.expansion.state[3] = Math.floor(value / 255); + this.deviceEx.expansion.last = -1; +}; + +Module.prototype.addSetCompassValue = function(value) { + this.deviceEx.compass.start = this.device.compass - (value % 255); + this.deviceEx.compass.state[3] = Math.floor(value / 255); + this.deviceEx.compass.last = -1; +}; + +module.exports = new Module(); diff --git a/app/modules/alux_nemo.json b/app/modules/alux_nemo.json new file mode 100644 index 000000000..bb4c01d44 --- /dev/null +++ b/app/modules/alux_nemo.json @@ -0,0 +1,31 @@ +{ + "id": "630101", + "name": { + "en": "NEMO", + "ko": "네모" + }, + "category": "module", + "platform": ["win32", "darwin"], + "icon": "alux_nemo.png", + "module": "alux_nemo.js", + "driver": { + "win32-ia32": "CH34x_Install_Windows_v3_4/CH34x_Install_Windows_v3_4.exe", + "win32-x64": "CH34x_Install_Windows_v3_4/CH34x_Install_Windows_v3_4.exe" + }, + "url": "https://www.aluxonline.com/", + "firmware": "alux_nemo", + "firmwareBaudRate": 115200, + "email": "contact@imssam.me", + "reconnect": true, + "selectPort": true, + "hardware": { + "type": "serial", + "control": "slave", + "duration": 50, + "vendor": "wch.cn", + "baudRate": 115200, + "lostTimer": 1000, + "softwareReset": false, + "firmwarecheck": false + } +} diff --git a/app/modules/alux_nemo.png b/app/modules/alux_nemo.png new file mode 100644 index 000000000..bc4ccf565 Binary files /dev/null and b/app/modules/alux_nemo.png differ diff --git a/app/modules/choco.js b/app/modules/choco.js index 4befe1515..7a2c3cd0f 100644 --- a/app/modules/choco.js +++ b/app/modules/choco.js @@ -10,43 +10,35 @@ class Choco extends BaseModule { super(); this.crctab16 = new Uint16Array([ - 0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, - 0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, - 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E, - 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, - 0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, - 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, - 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C, - 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, - 0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, - 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3, - 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A, - 0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, - 0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, - 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1, - 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, - 0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, - 0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7, - 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF, - 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, - 0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, - 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5, - 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD, - 0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, - 0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, - 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3, - 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, - 0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, - 0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, - 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1, - 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, - 0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, - 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78, + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, + 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, + 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, + 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, + 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, + 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, + 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, + 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, + 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, + 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, + 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, + 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, + 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, + 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, + 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, + 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, + 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, + 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, + 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, + 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, + 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, + 0x2c6a, 0x1ef1, 0x0f78, ]); this.SEND_PACKET = { - START: 0x7C, - END: 0x7E, + START: 0x7c, + END: 0x7e, }; this.cmdSeq = 0; @@ -62,6 +54,7 @@ class Choco extends BaseModule { this.executeCheckList = []; this.executeCount = 0; + // this.previousSensorData = {}; this.sensorData = { is_front_sensor: false, is_bottom_sensor: false, @@ -90,7 +83,7 @@ class Choco extends BaseModule { }, }; - this.ledStatus = [0,0,0]; //right, left, rear + this.ledStatus = [0, 0, 0]; //right, left, rear } // #endregion Constructor @@ -133,29 +126,29 @@ class Choco extends BaseModule { }); //return cmdPing; }); - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } - }; + } return null; - }; + } // 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다. checkInitialData(data, config) { return true; - }; + } // 주기적으로 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. validateLocalData(data) { return true; - }; + } /* 하드웨어 기기에 전달할 데이터를 반환합니다. slave 모드인 경우 duration 속성 간격으로 지속적으로 기기에 요청을 보냅니다. */ requestLocalData() { - //this.log('BASE - requestLocalData()'); + //this.log('BASE - requestLocalData()'); if (!this.isConnect) { return; } @@ -171,7 +164,7 @@ class Choco extends BaseModule { this.serialport.write(cmdReady, () => { this.serialport.drain(); }); - }; + } } if (this.sendBuffers.length > 0) { @@ -185,15 +178,15 @@ class Choco extends BaseModule { this.executeCmd.processing = 'started'; }); }); - }; + } } return; - }; + } /** * 하드웨어에서 온 데이터 처리 - * @param {*} data + * @param {*} data */ handleLocalData(data) { //this.log(`BASE - handleLocalData(): ${data.toString('hex')}`); @@ -244,27 +237,27 @@ class Choco extends BaseModule { if (this.sensorData.light_sensor > this.sensorInit.sensor2.max) { this.sensorData.light_sensor = this.sensorInit.sensor2.max; } - this.sensorData.is_front_sensor = - (this.sensorData.front_sensor < this.sensorInit.sensor0.threshold); - this.sensorData.is_bottom_sensor = - (this.sensorData.bottom_sensor > this.sensorInit.sensor1.threshold); - this.sensorData.is_light_sensor = - (this.sensorData.light_sensor < this.sensorInit.sensor2.threshold); + this.sensorData.is_front_sensor = + this.sensorData.front_sensor < this.sensorInit.sensor0.threshold; + this.sensorData.is_bottom_sensor = + this.sensorData.bottom_sensor > this.sensorInit.sensor1.threshold; + this.sensorData.is_light_sensor = + this.sensorData.light_sensor < this.sensorInit.sensor2.threshold; let fVal = this.sensorData.front_sensor; const fMin = this.sensorInit.sensor0.min; const fMmax = this.sensorInit.sensor0.max; - fVal = (fVal - fMin) * 100 / (fMmax - fMin); + fVal = ((fVal - fMin) * 100) / (fMmax - fMin); let bVal = this.sensorData.bottom_sensor; const bMin = this.sensorInit.sensor1.min; const bMmax = this.sensorInit.sensor1.max; - bVal = (bVal - bMin) * 100 / (bMmax - bMin); + bVal = ((bVal - bMin) * 100) / (bMmax - bMin); let lVal = this.sensorData.light_sensor; const lMin = this.sensorInit.sensor2.min; const lMmax = this.sensorInit.sensor2.max; - lVal = (lVal - lMin) * 100 / (lMmax - lMin); + lVal = ((lVal - lMin) * 100) / (lMmax - lMin); this.sensorData.front_sensor = parseInt(fVal, 10); if (this.sensorData.front_sensor < 0) { @@ -286,7 +279,7 @@ class Choco extends BaseModule { } } - // console.log(`command:${command}, len: ${decodedData.length}`, + // console.log(`command:${command}, len: ${decodedData.length}`, // `data:${data.toString('hex')}, seqNo:${seqNo}`, // `${sensor0},${sensor1},${sensor2}`, // `${this.sensorData.is_front_sensor},`, @@ -300,27 +293,37 @@ class Choco extends BaseModule { } } } - }; + } /** * 엔트리로 전달할 데이터 - * @param {*} handler + * @param {*} handler */ requestRemoteData(handler) { + //sensor데이터는 상태가 바뀔때 전송한다. + // if ( + // _.isEmpty(this.previousSensorData) || + // !_.isEqual(this.previousSensorData, this.sensorData) + // ) { + // handler.write('sensorData', this.sensorData); + // this.previousSensorData = _.cloneDeep(this.sensorData); + // } + handler.write('sensorData', this.sensorData); + if (this.executeCmd.processing === 'done') { this.log('requestRemoteData done', this.executeCmd.id); handler.write('msg_id', this.executeCmd.id); - handler.write('sensorData', this.sensorData); + //handler.write('sensorData', this.sensorData); this.executeCmd.id = ''; this.executeCmd.processing = 'none'; } - }; + } /** * 엔트리에서 받은 데이터에 대한 처리 - * @param {*} handler + * @param {*} handler */ handleRemoteData(handler) { if (!this.isConnect) { @@ -346,7 +349,7 @@ class Choco extends BaseModule { connect() { this.isConnect = true; this.sensorInit.inited = 'none'; - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } disconnect(connect) { @@ -363,9 +366,9 @@ class Choco extends BaseModule { this.sensorInit.inited = 'none'; }); }); - this.isSendInitData = false; + this.isSendInitData = false; } - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } /* @@ -376,8 +379,6 @@ class Choco extends BaseModule { } // #endregion Base Functions for Entry - - /*************************************************************************************** * 프로토롤 제어 함수 ***************************************************************************************/ @@ -415,14 +416,14 @@ class Choco extends BaseModule { } if (retval > 990) { retval = 990; - } + } return retval; } calTurnVal(args) { let retval = 0; if (args.param2 === 'degree') { - retval = parseInt(args.param1 * 10 / 90, 10); + retval = parseInt((args.param1 * 10) / 90, 10); if (args.param1 > 0 && retval === 0) { retval = 1; } @@ -477,36 +478,41 @@ class Choco extends BaseModule { case 'ping': data = Buffer.from([0x03, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping2': data = Buffer.from([0x13, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping3': data = Buffer.from([0x14, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping2_end': data = Buffer.from([0x17, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ready': data = Buffer.from([0x04, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_forward': @@ -517,43 +523,47 @@ class Choco extends BaseModule { } data.writeUInt32LE(this.calMoveVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_backward': if (args.param2 === 'cm') { - data = Buffer.from([0x1A, seqNo, 0, 0, 0, 0]); + data = Buffer.from([0x1a, seqNo, 0, 0, 0, 0]); } else { data = Buffer.from([0x06, seqNo, 0, 0, 0, 0]); } data.writeUInt32LE(this.calMoveVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'turn_left': data = Buffer.from([0x07, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(this.calTurnVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'turn_right': data = Buffer.from([0x08, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(this.calTurnVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_right_left': { if (args.param3 === 'cm') { - data = Buffer.from([0x1B, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); + data = Buffer.from([0x1b, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); } else { - data = Buffer.from([0x0D, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); + data = Buffer.from([0x0d, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); } const args1 = { param1: args.param1, @@ -564,30 +574,33 @@ class Choco extends BaseModule { param2: args.param3, }; data.writeUInt32LE(this.calMoveVal(args1), 2); - data.writeUInt32LE(this.calMoveVal(args2), 6); + data.writeUInt32LE(this.calMoveVal(args2), 6); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'onoff_led_rear': { - const rearLed = (args.param1 === 'On') ? 1 : 0; + const rearLed = args.param1 === 'On' ? 1 : 0; this.ledStatus[2] = rearLed; - data = Buffer.from([0x0B, seqNo, this.ledStatus[0], this.ledStatus[1], this.ledStatus[2]]); + data = Buffer.from([ + 0x0b, + seqNo, + this.ledStatus[0], + this.ledStatus[1], + this.ledStatus[2], + ]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'set_led_color': { - const { - rightLed, - leftLed, - } = this.calLedCol(args); + const { rightLed, leftLed } = this.calLedCol(args); if (args.param1 === 'right') { this.ledStatus[0] = rightLed; } else if (args.param1 === 'left') { @@ -596,29 +609,35 @@ class Choco extends BaseModule { this.ledStatus[0] = rightLed; this.ledStatus[1] = leftLed; } - data = Buffer.from([0x0B, seqNo, this.ledStatus[0], this.ledStatus[1], this.ledStatus[2]]); + data = Buffer.from([ + 0x0b, + seqNo, + this.ledStatus[0], + this.ledStatus[1], + this.ledStatus[2], + ]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'play_sound': - data = Buffer.from([0x0F, seqNo, 0, 0, 0, 0]); + data = Buffer.from([0x0f, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(args.param1, 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - const cmdData = Buffer.from([0x7C, ...encodedCmd, 0x7E]); + const cmdData = Buffer.from([0x7c, ...encodedCmd, 0x7e]); //console.log(cmdData); return cmdData; } - /*************************************************************************************** * 데이터 encoding ***************************************************************************************/ @@ -626,17 +645,17 @@ class Choco extends BaseModule { const buffer = Buffer.alloc(data.length * 2); let idx = 0; for (const d of data) { - if (d === 0x7C) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5C; + if (d === 0x7c) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5c; idx += 2; - } else if (d === 0x7D) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5D; + } else if (d === 0x7d) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5d; idx += 2; - } else if (d === 0x7E) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5E; + } else if (d === 0x7e) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5e; idx += 2; } else { buffer[idx] = d; @@ -652,8 +671,8 @@ class Choco extends BaseModule { escapeEecode(data) { const buffer = Buffer.alloc(data.length); let idx = 0; - for (let i = 0; i < data.length;) { - if (data[i] === 0x7D) { + for (let i = 0; i < data.length; ) { + if (data[i] === 0x7d) { buffer[idx++] = data[i + 1] ^ 0x20; i += 2; } else { @@ -673,7 +692,7 @@ class Choco extends BaseModule { res = ((res >> 8) & 0x0ff) ^ this.crctab16[(res ^ b) & 0xff]; } - return (~res) & 0x0ffff; + return ~res & 0x0ffff; } /*************************************************************************************** diff --git a/app/modules/choco2.js b/app/modules/choco2.js index 4befe1515..7a2c3cd0f 100644 --- a/app/modules/choco2.js +++ b/app/modules/choco2.js @@ -10,43 +10,35 @@ class Choco extends BaseModule { super(); this.crctab16 = new Uint16Array([ - 0X0000, 0X1189, 0X2312, 0X329B, 0X4624, 0X57AD, 0X6536, 0X74BF, - 0X8C48, 0X9DC1, 0XAF5A, 0XBED3, 0XCA6C, 0XDBE5, 0XE97E, 0XF8F7, - 0X1081, 0X0108, 0X3393, 0X221A, 0X56A5, 0X472C, 0X75B7, 0X643E, - 0X9CC9, 0X8D40, 0XBFDB, 0XAE52, 0XDAED, 0XCB64, 0XF9FF, 0XE876, - 0X2102, 0X308B, 0X0210, 0X1399, 0X6726, 0X76AF, 0X4434, 0X55BD, - 0XAD4A, 0XBCC3, 0X8E58, 0X9FD1, 0XEB6E, 0XFAE7, 0XC87C, 0XD9F5, - 0X3183, 0X200A, 0X1291, 0X0318, 0X77A7, 0X662E, 0X54B5, 0X453C, - 0XBDCB, 0XAC42, 0X9ED9, 0X8F50, 0XFBEF, 0XEA66, 0XD8FD, 0XC974, - 0X4204, 0X538D, 0X6116, 0X709F, 0X0420, 0X15A9, 0X2732, 0X36BB, - 0XCE4C, 0XDFC5, 0XED5E, 0XFCD7, 0X8868, 0X99E1, 0XAB7A, 0XBAF3, - 0X5285, 0X430C, 0X7197, 0X601E, 0X14A1, 0X0528, 0X37B3, 0X263A, - 0XDECD, 0XCF44, 0XFDDF, 0XEC56, 0X98E9, 0X8960, 0XBBFB, 0XAA72, - 0X6306, 0X728F, 0X4014, 0X519D, 0X2522, 0X34AB, 0X0630, 0X17B9, - 0XEF4E, 0XFEC7, 0XCC5C, 0XDDD5, 0XA96A, 0XB8E3, 0X8A78, 0X9BF1, - 0X7387, 0X620E, 0X5095, 0X411C, 0X35A3, 0X242A, 0X16B1, 0X0738, - 0XFFCF, 0XEE46, 0XDCDD, 0XCD54, 0XB9EB, 0XA862, 0X9AF9, 0X8B70, - 0X8408, 0X9581, 0XA71A, 0XB693, 0XC22C, 0XD3A5, 0XE13E, 0XF0B7, - 0X0840, 0X19C9, 0X2B52, 0X3ADB, 0X4E64, 0X5FED, 0X6D76, 0X7CFF, - 0X9489, 0X8500, 0XB79B, 0XA612, 0XD2AD, 0XC324, 0XF1BF, 0XE036, - 0X18C1, 0X0948, 0X3BD3, 0X2A5A, 0X5EE5, 0X4F6C, 0X7DF7, 0X6C7E, - 0XA50A, 0XB483, 0X8618, 0X9791, 0XE32E, 0XF2A7, 0XC03C, 0XD1B5, - 0X2942, 0X38CB, 0X0A50, 0X1BD9, 0X6F66, 0X7EEF, 0X4C74, 0X5DFD, - 0XB58B, 0XA402, 0X9699, 0X8710, 0XF3AF, 0XE226, 0XD0BD, 0XC134, - 0X39C3, 0X284A, 0X1AD1, 0X0B58, 0X7FE7, 0X6E6E, 0X5CF5, 0X4D7C, - 0XC60C, 0XD785, 0XE51E, 0XF497, 0X8028, 0X91A1, 0XA33A, 0XB2B3, - 0X4A44, 0X5BCD, 0X6956, 0X78DF, 0X0C60, 0X1DE9, 0X2F72, 0X3EFB, - 0XD68D, 0XC704, 0XF59F, 0XE416, 0X90A9, 0X8120, 0XB3BB, 0XA232, - 0X5AC5, 0X4B4C, 0X79D7, 0X685E, 0X1CE1, 0X0D68, 0X3FF3, 0X2E7A, - 0XE70E, 0XF687, 0XC41C, 0XD595, 0XA12A, 0XB0A3, 0X8238, 0X93B1, - 0X6B46, 0X7ACF, 0X4854, 0X59DD, 0X2D62, 0X3CEB, 0X0E70, 0X1FF9, - 0XF78F, 0XE606, 0XD49D, 0XC514, 0XB1AB, 0XA022, 0X92B9, 0X8330, - 0X7BC7, 0X6A4E, 0X58D5, 0X495C, 0X3DE3, 0X2C6A, 0X1EF1, 0X0F78, + 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, + 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, + 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, + 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, + 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, + 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, + 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, + 0x99e1, 0xab7a, 0xbaf3, 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, + 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, + 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, + 0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, + 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581, 0xa71a, 0xb693, + 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, + 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 0x0948, + 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, + 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, + 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, + 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, + 0xa33a, 0xb2b3, 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, + 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e, + 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, + 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 0xe606, + 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, + 0x2c6a, 0x1ef1, 0x0f78, ]); this.SEND_PACKET = { - START: 0x7C, - END: 0x7E, + START: 0x7c, + END: 0x7e, }; this.cmdSeq = 0; @@ -62,6 +54,7 @@ class Choco extends BaseModule { this.executeCheckList = []; this.executeCount = 0; + // this.previousSensorData = {}; this.sensorData = { is_front_sensor: false, is_bottom_sensor: false, @@ -90,7 +83,7 @@ class Choco extends BaseModule { }, }; - this.ledStatus = [0,0,0]; //right, left, rear + this.ledStatus = [0, 0, 0]; //right, left, rear } // #endregion Constructor @@ -133,29 +126,29 @@ class Choco extends BaseModule { }); //return cmdPing; }); - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } - }; + } return null; - }; + } // 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다. checkInitialData(data, config) { return true; - }; + } // 주기적으로 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. validateLocalData(data) { return true; - }; + } /* 하드웨어 기기에 전달할 데이터를 반환합니다. slave 모드인 경우 duration 속성 간격으로 지속적으로 기기에 요청을 보냅니다. */ requestLocalData() { - //this.log('BASE - requestLocalData()'); + //this.log('BASE - requestLocalData()'); if (!this.isConnect) { return; } @@ -171,7 +164,7 @@ class Choco extends BaseModule { this.serialport.write(cmdReady, () => { this.serialport.drain(); }); - }; + } } if (this.sendBuffers.length > 0) { @@ -185,15 +178,15 @@ class Choco extends BaseModule { this.executeCmd.processing = 'started'; }); }); - }; + } } return; - }; + } /** * 하드웨어에서 온 데이터 처리 - * @param {*} data + * @param {*} data */ handleLocalData(data) { //this.log(`BASE - handleLocalData(): ${data.toString('hex')}`); @@ -244,27 +237,27 @@ class Choco extends BaseModule { if (this.sensorData.light_sensor > this.sensorInit.sensor2.max) { this.sensorData.light_sensor = this.sensorInit.sensor2.max; } - this.sensorData.is_front_sensor = - (this.sensorData.front_sensor < this.sensorInit.sensor0.threshold); - this.sensorData.is_bottom_sensor = - (this.sensorData.bottom_sensor > this.sensorInit.sensor1.threshold); - this.sensorData.is_light_sensor = - (this.sensorData.light_sensor < this.sensorInit.sensor2.threshold); + this.sensorData.is_front_sensor = + this.sensorData.front_sensor < this.sensorInit.sensor0.threshold; + this.sensorData.is_bottom_sensor = + this.sensorData.bottom_sensor > this.sensorInit.sensor1.threshold; + this.sensorData.is_light_sensor = + this.sensorData.light_sensor < this.sensorInit.sensor2.threshold; let fVal = this.sensorData.front_sensor; const fMin = this.sensorInit.sensor0.min; const fMmax = this.sensorInit.sensor0.max; - fVal = (fVal - fMin) * 100 / (fMmax - fMin); + fVal = ((fVal - fMin) * 100) / (fMmax - fMin); let bVal = this.sensorData.bottom_sensor; const bMin = this.sensorInit.sensor1.min; const bMmax = this.sensorInit.sensor1.max; - bVal = (bVal - bMin) * 100 / (bMmax - bMin); + bVal = ((bVal - bMin) * 100) / (bMmax - bMin); let lVal = this.sensorData.light_sensor; const lMin = this.sensorInit.sensor2.min; const lMmax = this.sensorInit.sensor2.max; - lVal = (lVal - lMin) * 100 / (lMmax - lMin); + lVal = ((lVal - lMin) * 100) / (lMmax - lMin); this.sensorData.front_sensor = parseInt(fVal, 10); if (this.sensorData.front_sensor < 0) { @@ -286,7 +279,7 @@ class Choco extends BaseModule { } } - // console.log(`command:${command}, len: ${decodedData.length}`, + // console.log(`command:${command}, len: ${decodedData.length}`, // `data:${data.toString('hex')}, seqNo:${seqNo}`, // `${sensor0},${sensor1},${sensor2}`, // `${this.sensorData.is_front_sensor},`, @@ -300,27 +293,37 @@ class Choco extends BaseModule { } } } - }; + } /** * 엔트리로 전달할 데이터 - * @param {*} handler + * @param {*} handler */ requestRemoteData(handler) { + //sensor데이터는 상태가 바뀔때 전송한다. + // if ( + // _.isEmpty(this.previousSensorData) || + // !_.isEqual(this.previousSensorData, this.sensorData) + // ) { + // handler.write('sensorData', this.sensorData); + // this.previousSensorData = _.cloneDeep(this.sensorData); + // } + handler.write('sensorData', this.sensorData); + if (this.executeCmd.processing === 'done') { this.log('requestRemoteData done', this.executeCmd.id); handler.write('msg_id', this.executeCmd.id); - handler.write('sensorData', this.sensorData); + //handler.write('sensorData', this.sensorData); this.executeCmd.id = ''; this.executeCmd.processing = 'none'; } - }; + } /** * 엔트리에서 받은 데이터에 대한 처리 - * @param {*} handler + * @param {*} handler */ handleRemoteData(handler) { if (!this.isConnect) { @@ -346,7 +349,7 @@ class Choco extends BaseModule { connect() { this.isConnect = true; this.sensorInit.inited = 'none'; - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } disconnect(connect) { @@ -363,9 +366,9 @@ class Choco extends BaseModule { this.sensorInit.inited = 'none'; }); }); - this.isSendInitData = false; + this.isSendInitData = false; } - this.ledStatus = [0,0,0]; + this.ledStatus = [0, 0, 0]; } /* @@ -376,8 +379,6 @@ class Choco extends BaseModule { } // #endregion Base Functions for Entry - - /*************************************************************************************** * 프로토롤 제어 함수 ***************************************************************************************/ @@ -415,14 +416,14 @@ class Choco extends BaseModule { } if (retval > 990) { retval = 990; - } + } return retval; } calTurnVal(args) { let retval = 0; if (args.param2 === 'degree') { - retval = parseInt(args.param1 * 10 / 90, 10); + retval = parseInt((args.param1 * 10) / 90, 10); if (args.param1 > 0 && retval === 0) { retval = 1; } @@ -477,36 +478,41 @@ class Choco extends BaseModule { case 'ping': data = Buffer.from([0x03, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping2': data = Buffer.from([0x13, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping3': data = Buffer.from([0x14, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ping2_end': data = Buffer.from([0x17, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'ready': data = Buffer.from([0x04, seqNo]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_forward': @@ -517,43 +523,47 @@ class Choco extends BaseModule { } data.writeUInt32LE(this.calMoveVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_backward': if (args.param2 === 'cm') { - data = Buffer.from([0x1A, seqNo, 0, 0, 0, 0]); + data = Buffer.from([0x1a, seqNo, 0, 0, 0, 0]); } else { data = Buffer.from([0x06, seqNo, 0, 0, 0, 0]); } data.writeUInt32LE(this.calMoveVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'turn_left': data = Buffer.from([0x07, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(this.calTurnVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'turn_right': data = Buffer.from([0x08, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(this.calTurnVal(args), 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; case 'move_right_left': { if (args.param3 === 'cm') { - data = Buffer.from([0x1B, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); + data = Buffer.from([0x1b, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); } else { - data = Buffer.from([0x0D, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); + data = Buffer.from([0x0d, seqNo, 0, 0, 0, 0, 0, 0, 0, 0]); } const args1 = { param1: args.param1, @@ -564,30 +574,33 @@ class Choco extends BaseModule { param2: args.param3, }; data.writeUInt32LE(this.calMoveVal(args1), 2); - data.writeUInt32LE(this.calMoveVal(args2), 6); + data.writeUInt32LE(this.calMoveVal(args2), 6); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'onoff_led_rear': { - const rearLed = (args.param1 === 'On') ? 1 : 0; + const rearLed = args.param1 === 'On' ? 1 : 0; this.ledStatus[2] = rearLed; - data = Buffer.from([0x0B, seqNo, this.ledStatus[0], this.ledStatus[1], this.ledStatus[2]]); + data = Buffer.from([ + 0x0b, + seqNo, + this.ledStatus[0], + this.ledStatus[1], + this.ledStatus[2], + ]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'set_led_color': { - const { - rightLed, - leftLed, - } = this.calLedCol(args); + const { rightLed, leftLed } = this.calLedCol(args); if (args.param1 === 'right') { this.ledStatus[0] = rightLed; } else if (args.param1 === 'left') { @@ -596,29 +609,35 @@ class Choco extends BaseModule { this.ledStatus[0] = rightLed; this.ledStatus[1] = leftLed; } - data = Buffer.from([0x0B, seqNo, this.ledStatus[0], this.ledStatus[1], this.ledStatus[2]]); + data = Buffer.from([ + 0x0b, + seqNo, + this.ledStatus[0], + this.ledStatus[1], + this.ledStatus[2], + ]); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - case 'play_sound': - data = Buffer.from([0x0F, seqNo, 0, 0, 0, 0]); + data = Buffer.from([0x0f, seqNo, 0, 0, 0, 0]); data.writeUInt32LE(args.param1, 2); crc = this.calCrc16(data); - encodedCmd = this.escapeEncode(Buffer.concat([data, - Buffer.from([crc & 0xFF, (crc >> 8) & 0xFF])])); + encodedCmd = this.escapeEncode( + Buffer.concat([data, Buffer.from([crc & 0xff, (crc >> 8) & 0xff])]) + ); break; } - const cmdData = Buffer.from([0x7C, ...encodedCmd, 0x7E]); + const cmdData = Buffer.from([0x7c, ...encodedCmd, 0x7e]); //console.log(cmdData); return cmdData; } - /*************************************************************************************** * 데이터 encoding ***************************************************************************************/ @@ -626,17 +645,17 @@ class Choco extends BaseModule { const buffer = Buffer.alloc(data.length * 2); let idx = 0; for (const d of data) { - if (d === 0x7C) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5C; + if (d === 0x7c) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5c; idx += 2; - } else if (d === 0x7D) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5D; + } else if (d === 0x7d) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5d; idx += 2; - } else if (d === 0x7E) { - buffer[idx] = 0x7D; - buffer[idx + 1] = 0x5E; + } else if (d === 0x7e) { + buffer[idx] = 0x7d; + buffer[idx + 1] = 0x5e; idx += 2; } else { buffer[idx] = d; @@ -652,8 +671,8 @@ class Choco extends BaseModule { escapeEecode(data) { const buffer = Buffer.alloc(data.length); let idx = 0; - for (let i = 0; i < data.length;) { - if (data[i] === 0x7D) { + for (let i = 0; i < data.length; ) { + if (data[i] === 0x7d) { buffer[idx++] = data[i + 1] ^ 0x20; i += 2; } else { @@ -673,7 +692,7 @@ class Choco extends BaseModule { res = ((res >> 8) & 0x0ff) ^ this.crctab16[(res ^ b) & 0xff]; } - return (~res) & 0x0ffff; + return ~res & 0x0ffff; } /*************************************************************************************** diff --git a/app/modules/neo_cannon.js b/app/modules/neo_cannon.js index 3974b63e1..25765e8d8 100644 --- a/app/modules/neo_cannon.js +++ b/app/modules/neo_cannon.js @@ -1,6 +1,7 @@ function Module() { - this.tx_max_len = 14; + this.tx_max_len = 68; this.tx_data = new Array(this.tx_max_len); + this.PIXEL_NUM = 18; this.sensor_data = { vibe: 0, @@ -16,6 +17,26 @@ function Module() { d9: 0, d10: 0, angle_state: 0, + neopixel: [ + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + { r: 0, g: 0, b: 0 }, + ], }; this.sensorValueSize = { @@ -38,45 +59,47 @@ const NEOCANNON = { D9: 'd9', D10: 'd10', ANGLE_STATE: 'angleState', + NEOPIXEL: 'neopixel', }; -Module.prototype.init = function(handler, config) {}; +Module.prototype.init = function (handler, config) {}; -Module.prototype.setSerialPort = function(sp) { +Module.prototype.setSerialPort = function (sp) { this.sp = sp; }; -Module.prototype.requestInitialData = function() { +Module.prototype.requestInitialData = function () { const txData = this.tx_data; + const dataLen = this.tx_max_len; txData[0] = 0xff; - txData[1] = 0x0e; + txData[1] = 0x44; txData[2] = 0x01; txData[3] = 0x03; - for (let i = 4; i < this.tx_max_len - 2; i++) { + for (let i = 4; i < dataLen - 2; i++) { txData[i] = 0; } - txData[12] = 0x4; - txData[13] = 0xa; + txData[dataLen - 2] = 0x4; + txData[dataLen - 1] = 0xa; return txData; }; -Module.prototype.checkInitialData = function(data, config) { +Module.prototype.checkInitialData = function (data, config) { return true; }; -Module.prototype.afterConnect = function(that, cb) { +Module.prototype.afterConnect = function (that, cb) { that.connected = true; if (cb) { cb('connected'); } }; -Module.prototype.validateLocalData = function(data) { +Module.prototype.validateLocalData = function (data) { return true; }; /* 엔트리HW -> 엔트리JS */ -Module.prototype.requestRemoteData = function(handler) { +Module.prototype.requestRemoteData = function (handler) { const sensorData = this.sensor_data; for (const key in sensorData) { handler.write(key, sensorData[key]); @@ -84,7 +107,7 @@ Module.prototype.requestRemoteData = function(handler) { }; /** 엔트리JS -> 엔트리HW */ -Module.prototype.handleRemoteData = function(handler) { +Module.prototype.handleRemoteData = function (handler) { const workerData = this.worker_data; let newValue; @@ -136,18 +159,46 @@ Module.prototype.handleRemoteData = function(handler) { workerData.angle_state = newValue; } + if (handler.e(NEOCANNON.NEOPIXEL)) { + newValue = handler.read(NEOCANNON.NEOPIXEL); + if (newValue.data) { + const red = newValue.data.red; + const green = newValue.data.green; + const blue = newValue.data.blue; + + if (newValue.data.num !== undefined) { + const num = newValue.data.num; + workerData.neopixel[num].r = red; + workerData.neopixel[num].g = green; + workerData.neopixel[num].b = blue; + } else { + for (let i = 0; i < this.PIXEL_NUM; i++) { + workerData.neopixel[i].r = red; + workerData.neopixel[i].g = green; + workerData.neopixel[i].b = blue; + } + } + } else { + for (let i = 0; i < this.PIXEL_NUM; i++) { + workerData.neopixel[i].r = 0; + workerData.neopixel[i].g = 0; + workerData.neopixel[i].b = 0; + } + } + } + this.worker_data = workerData; }; /* 엔트리HW -> 교구 */ -Module.prototype.requestLocalData = function() { +Module.prototype.requestLocalData = function () { const workerData = this.worker_data; const txData = this.tx_data; let checkSum = 0; const dataLen = txData.length; txData[0] = 0xff; - txData[1] = 0x0e; + txData[1] = 0x44; txData[2] = 0x01; txData[3] = 0x03; txData[4] = workerData.buz_octave; @@ -158,7 +209,14 @@ Module.prototype.requestLocalData = function() { txData[9] = workerData.d9; txData[10] = workerData.d10; txData[11] = workerData.angle_state; - txData[13] = 0xa; + + for (let i = 0; i < this.PIXEL_NUM; i++) { + txData[i * 3 + 12] = workerData.neopixel[i].r; + txData[i * 3 + 13] = workerData.neopixel[i].g; + txData[i * 3 + 14] = workerData.neopixel[i].b; + } + + txData[dataLen - 1] = 0xa; for (let i = 2; i < dataLen - 2; i++) { checkSum += txData[i]; @@ -171,7 +229,7 @@ Module.prototype.requestLocalData = function() { }; /* 교구 -> 엔트리HW */ -Module.prototype.handleLocalData = function(data) { +Module.prototype.handleLocalData = function (data) { const datas = this.getDataByBuffer(data); const sensorData = this.sensor_data; @@ -199,7 +257,7 @@ Module.prototype.handleLocalData = function(data) { this.sensor_data = sensorData; }; -Module.prototype.getDataByBuffer = function(buffer) { +Module.prototype.getDataByBuffer = function (buffer) { const datas = []; let lastIndex = 0; buffer.forEach((value, idx) => { @@ -211,14 +269,14 @@ Module.prototype.getDataByBuffer = function(buffer) { return datas; }; -Module.prototype.disconnect = function(connect) { +Module.prototype.disconnect = function (connect) { connect.close(); if (this.sp) { delete this.sp; } }; -Module.prototype.reset = function() { +Module.prototype.reset = function () { this.lastTime = 0; this.lastSendTime = 0; }; diff --git a/app/modules/robotis_RB100_practice.js b/app/modules/robotis_RB100_practice.js index deb5f7195..c11f85ab9 100644 --- a/app/modules/robotis_RB100_practice.js +++ b/app/modules/robotis_RB100_practice.js @@ -569,29 +569,40 @@ Module.prototype.handleLocalData = function(data) { // data: Native Buffer } } + const dxlPositionStartAddr = + addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1]; + // DXL Position for (let i = 0; i < 20; i++) { - const currentId = rxPacket.data[2 + 83 + (3 * i)]; - const currentPos = rxPacket.data[2 + 83 + (3 * i) + 1] + - (rxPacket.data[2 + 83 + (3 * i) + 2] << 8); - if (currentId != 0xFF && currentPos != 0xFFFF) { + const currentId = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i]; + const currentPos = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] + + (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8); + if (currentId != 0xff && currentPos != 0xffff) { this.dxlPositions[currentId] = currentPos; } } + const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20; + // line category this.dataBuffer[5201] = rxPacket.data[2 + 143]; + + const sensorStartAddr = lineCategoryStartAddr + 1; // 온습도+조도+동작감지센서값 - this.pirPir[0] = rxPacket.data[2 + 144]; - this.pirTemperature[0] = rxPacket.data[2 + 145]; - this.pirHumidity[0] = rxPacket.data[2 + 146]; - this.pirBrightness[0] = rxPacket.data[2 + 147]; + this.pirPir[0] = rxPacket.data[2 + sensorStartAddr]; + this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1]; + this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2]; + this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3]; // 거리+버튼+조도센서값 - this.distanceDistance[0] = rxPacket.data[2 + 148] + (rxPacket.data[2 + 149] << 8); - this.distanceButton[0] = rxPacket.data[2 + 150]; - this.distanceBrightness[0] = rxPacket.data[2 + 151]; + this.distanceDistance[0] = + rxPacket.data[2 + sensorStartAddr + 4] + + (rxPacket.data[2 + sensorStartAddr + 5] << 8); + this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6]; + this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7]; for (let i = 0; i < addrMap2.length; i++) { switch (addrMap2[i][1]) { @@ -842,39 +853,40 @@ const addrMap = [ [69,8,502], [77,1,700], [78,1,810], - [79,1,5015], - [80,1,5030], - [81,1,5031], - [82,1,5040], + [79,1,2134], + [80,1,5015], + [81,1,5030], + [82,1,5031], + [83,1,5040], ]; const addrMap2 = [ - [152,1,4000], - [153,2,4003], - [155,1,4005], - [156,1,4006], - [157,2,4009], - [159,2,4011], - [161,2,4013], - [163,2,4015], - [165,2,4017], - [167,2,4019], - [169,2,4021], - [171,2,4023], - [173,2,4025], - [175,2,4027], - [177,1,4031], - [178,1,4032], - [179,1,4033], - [180,2,4036], - [182,2,4038], - [184,2,4040], - [186,2,4042], - [188,2,4044], - [190,2,4046], - [192,2,4048], - [194,2,4050], + [153,1,4000], + [154,2,4003], + [156,1,4005], + [157,1,4006], + [158,2,4009], + [160,2,4011], + [162,2,4013], + [164,2,4015], + [166,2,4017], + [168,2,4019], + [170,2,4021], + [172,2,4023], + [174,2,4025], + [176,2,4027], + [178,1,4031], + [179,1,4032], + [180,1,4033], + [181,2,4036], + [183,2,4038], + [185,2,4040], + [187,2,4042], + [189,2,4044], + [191,2,4046], + [193,2,4048], + [195,2,4050], ]; //const rxPacket = Object.assign({}, packet); diff --git a/app/server/mac/server.txt b/app/server/mac/server.txt index 204b6fac9..3d9b5cae9 100755 Binary files a/app/server/mac/server.txt and b/app/server/mac/server.txt differ diff --git a/app/server/win/server.exe b/app/server/win/server.exe index 5e6c4a20b..5cb1272bf 100644 Binary files a/app/server/win/server.exe and b/app/server/win/server.exe differ diff --git a/app/src/main/electron/serverProcessManager.ts b/app/src/main/electron/serverProcessManager.ts index 00662373c..1cedeb3f9 100644 --- a/app/src/main/electron/serverProcessManager.ts +++ b/app/src/main/electron/serverProcessManager.ts @@ -52,8 +52,8 @@ class ServerProcessManager { this._sendToChild('addRoomId', roomId); } - connectHardwareSuccess() { - this._sendToChild('connectHardwareSuccess'); + connectHardwareSuccess(hardwareId: string) { + this._sendToChild('connectHardwareSuccess', hardwareId); } connectHardwareFailed() { diff --git a/app/src/main/mainRouter.ts b/app/src/main/mainRouter.ts index 54f5fa666..9c1f27d72 100644 --- a/app/src/main/mainRouter.ts +++ b/app/src/main/mainRouter.ts @@ -22,7 +22,7 @@ interface IEntryServer { setRouter: (router: MainRouter) => void; open: () => void; disconnectHardware: () => void; - connectHardwareSuccess: () => void; + connectHardwareSuccess: (hardwareId: String) => void; connectHardwareFailed: () => void; addRoomIdsOnSecondInstance: (roomId: string) => void; send: (data: any) => void; @@ -320,7 +320,7 @@ class MainRouter { logger.verbose('entryServer, connector connection'); this.handler = new DataHandler(this.config.id); this._connectToServer(); - this.server.connectHardwareSuccess(); + this.server.connectHardwareSuccess(this.config.id); this.connector.connect(); // router 설정 후 실제 기기와의 통신 시작 } } diff --git a/build/entry-hw.nsi b/build/entry-hw.nsi index 7b1de1f1d..1df7ca896 100644 --- a/build/entry-hw.nsi +++ b/build/entry-hw.nsi @@ -14,7 +14,7 @@ !define PRODUCT_NAME "Entry_HW" !define PROTOCOL_NAME "entryhw" !define APP_NAME "Entry_HW.exe" -!define PRODUCT_VERSION "1.9.57" +!define PRODUCT_VERSION "1.9.58" !define PRODUCT_PUBLISHER "EntryLabs" !define PRODUCT_WEB_SITE "https://www.playentry.org/" diff --git a/package.json b/package.json index c35b4b61b..228fb9e87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "entry-hw", - "version": "1.9.57", + "version": "1.9.58", "description": "엔트리 하드웨어 연결 프로그램", "author": "EntryLabs", "main": "./app/src/index.bundle.js",