diff --git a/app/firmwares/c3coding_arduino.hex b/app/firmwares/c3coding_arduino.hex new file mode 100644 index 000000000..e33e1c813 --- /dev/null +++ b/app/firmwares/c3coding_arduino.hex @@ -0,0 +1,434 @@ +:100000000C9463000C948B000C948B000C948B006C +:100010000C948B000C948B000C948B000C94F502C8 +:100020000C948B000C948B000C948B000C94F303B9 +:100030000C948B000C948B000C948B000C948B0014 +:100040000C94A9030C948B000C9477030C9451032B +:100050000C948B000C948B000C948B000C948B00F4 +:100060000C948B000C948B000000000024002700EF +:100070002A0000000000250028002B0002000000DC +:100080000800020100000304070000000000000057 +:1000900000000000002300260029000404040404DA +:1000A0000404040202020202020303030303030125 +:1000B00002040810204080010204081020010204FC +:1000C00008102000F40411241FBECFEFD8E0DEBFDB +:1000D000CDBF11E0A0E0B1E0E8EDFAE102C005908B +:1000E0000D92A632B107D9F722E0A6E2B1E001C035 +:1000F0001D92AA38B207E1F710E0C3E6D0E004C0D1 +:100100002197FE010E94640DC236D107C9F70E94F3 +:1001100059050C946A0D0C940000AF92BF92CF92D7 +:10012000DF92EF92FF920F931F93CF93DF936C01B7 +:100130007B018B01040F151FEB015E01AE18BF0898 +:10014000C017D10759F06991D601ED91FC9101904A +:10015000F081E02DC6010995892B79F7C501DF9162 +:10016000CF911F910F91FF90EF90DF90CF90BF90B4 +:10017000AF90089542E050E063E271E080EB91E0DF +:100180000C948D00FC01538D448D252F30E0842F7D +:1001900090E0821B930B541710F0CF9608950197AF +:1001A0000895FC01918D828D981761F0A28DAE0F9C +:1001B000BF2FB11D5D968C91928D9F5F9F73928F23 +:1001C00090E008958FEF9FEF0895FC01918D828D4F +:1001D000981731F0828DE80FF11D858D90E008951C +:1001E0008FEF9FEF0895FC01918D228D892F90E074 +:1001F000805C9F4F821B91098F739927089580EB34 +:1002000091E00E94F30021E0892B09F420E0822F85 +:10021000089580E090E0892B29F00E94FF00811171 +:100220000C9400000895FC01A48DA80FB92FB11DF6 +:10023000A35ABF4F2C91848D90E001968F7399271C +:10024000848FA689B7892C93A089B1898C918370FA +:1002500080648C93938D848D981306C00288F389F3 +:10026000E02D80818F7D80830895EF92FF920F9320 +:100270001F93CF93DF93EC0181E0888F9B8D8C8D52 +:1002800098131AC0E889F989808185FF15C09FB746 +:10029000F894EE89FF896083E889F9898081837009 +:1002A000806480839FBF81E090E0DF91CF911F91B8 +:1002B0000F91FF90EF900895F62E0B8D10E00F5FD9 +:1002C0001F4F0F731127E02E8C8D8E110CC00FB6AF +:1002D00007FCFACFE889F989808185FFF5CFCE0147 +:1002E0000E941301F1CFEB8DEC0FFD2FF11DE35AAE +:1002F000FF4FF0829FB7F8940B8FEA89FB898081CA +:100300008062CFCFCF93DF93EC01888D8823B9F043 +:10031000AA89BB89E889F9898C9185FD03C0808110 +:1003200086FD0DC00FB607FCF7CF8C9185FFF2CF8D +:10033000808185FFEDCFCE010E941301E9CFDF91CF +:10034000CF910895833081F028F4813099F0823084 +:10035000A9F008958730A9F08830C9F08430B1F44D +:10036000809180008F7D03C0809180008F77809383 +:100370008000089584B58F7784BD089584B58F7DFE +:10038000FBCF8091B0008F778093B000089580916B +:10039000B0008F7DF9CF1F93CF93DF93282F30E0EC +:1003A000F901E358FF4F8491F901E155FF4FD491D2 +:1003B000F901E556FF4FC491CC23A9F0162F811106 +:1003C0000E94A201EC2FF0E0EE0FFF1FEE58FF4F4E +:1003D000A591B4918FB7F894EC91111108C0D09504 +:1003E000DE23DC938FBFDF91CF911F910895DE2B29 +:1003F000F8CF9091000189130BC0ECE7F0E0E49195 +:100400009FEF90930001E13049F028F0E23061F075 +:1004100060E00C94CB0110926E00FACF90916F00C7 +:100420009D7F90936F00F4CF909170009D7F90938B +:10043000700091E09093B0009091B100987F94602B +:100440009093B1001092B300E3CFCF93DF9390E08D +:10045000FC01E155FF4F249185569F4FFC0184918B +:100460008823D1F090E0880F991FFC01E859FF4FD5 +:10047000A591B491FC01EE58FF4FC591D491611143 +:100480000EC09FB7F8948C91E22FE0958E238C9349 +:100490002881E223E8839FBFDF91CF9108958FB732 +:1004A000F894EC91E22BEC938FBFF6CF3FB7F89422 +:1004B00080912C0190912D01A0912E01B0912F01DE +:1004C00026B5A89B05C02F3F19F00196A11DB11DAF +:1004D0003FBFBA2FA92F982F8827BC01CD01620FEB +:1004E000711D811D911D42E0660F771F881F991FA6 +:1004F0004A95D1F708958F929F92AF92BF92CF9273 +:10050000DF92EF92FF924B015C010E9456026B0159 +:100510007C010E9456026C197D098E099F09683E74 +:10052000734081059105A8F321E0821A9108A10882 +:10053000B10888EEC80E83E0D81EE11CF11C8114BE +:100540009104A104B10429F7FF90EF90DF90CF90C0 +:10055000BF90AF909F908F900895FC01EE0FFF1F0A +:10056000EC56FE4F20813181232B39F421E030E01D +:100570003183208361E00C9425020895682F80EB7D +:1005800091E00C9435018FEF0E94BE0285E50E9438 +:10059000BE020C94BA000F931F93CF93DF938B018D +:1005A000D82FC92F82E00E94BE02C801AD2FBC2FF8 +:1005B0008093260190932701A0932801B0932901ED +:1005C0000E94BE02812F0E94BE028D2F0E94BE0299 +:1005D0008C2FDF91CF911F910F910C94BE028FEF62 +:1005E0000E94BE0285E50C94BE021F920F920FB6C8 +:1005F0000F9211242F933F934F935F936F937F93A9 +:100600008F939F93AF93BF93EF93FF9380913701A5 +:1006100090913801A0913901B0913A01892B8A2B30 +:100620008B2BD1F190913201E0913301F0913401A3 +:100630008081892780838091370190913801A09132 +:100640003901B0913A01181619061A061B069CF4D6 +:100650008091370190913801A0913901B0913A0110 +:100660000197A109B1098093370190933801A093B4 +:100670003901B0933A01FF91EF91BF91AF919F91F2 +:100680008F917F916F915F914F913F912F910F903B +:100690000FBE0F901F901895809100010E94F901E4 +:1006A000EACF1F920F920FB60F9211242F933F9310 +:1006B0004F935F936F937F938F939F93AF93BF936A +:1006C000EF93FF9380EB91E00E941301FF91EF9174 +:1006D000BF91AF919F918F917F916F915F914F915A +:1006E0003F912F910F900FBE0F901F9018951F9262 +:1006F0000F920FB60F9211242F938F939F93EF9326 +:10070000FF93E091C001F091C1018081E091C601A9 +:10071000F091C70182FD1BC090818091C9018F5F5C +:100720008F732091CA01821741F0E091C901F0E076 +:10073000E055FE4F958F8093C901FF91EF919F91F6 +:100740008F912F910F900FBE0F901F901895808161 +:10075000F4CF1F920F920FB60F9211242F933F9355 +:100760008F939F93AF93BF938091530190915401C6 +:10077000A0915501B091560130912B0123E0230F38 +:100780002D3758F50196A11DB11D20932B018093A3 +:10079000530190935401A0935501B0935601809159 +:1007A0002C0190912D01A0912E01B0912F01019665 +:1007B000A11DB11D80932C0190932D01A0932E01BA +:1007C000B0932F01BF91AF919F918F913F912F9146 +:1007D0000F900FBE0F901F90189526E8230F0296DA +:1007E000A11DB11DD2CF1F920F920FB60F921124EF +:1007F0002F933F934F935F936F937F938F939F9329 +:10080000AF93BF93CF93DF93EF93FF9380912A0130 +:10081000C0917102D0E087FF24C010928500109231 +:10082000840080912A018F5F80932A0180912A01A0 +:10083000082E000C990B8C179D0724F480912A0137 +:100840008C30C4F1809184009091850004968034AE +:100850009C4908F47AC080918400909185000496A8 +:1008600076C080912A01082E000C990B8C179D07E9 +:10087000C4F6E0912A018E2FEE0F990BFC01EE0FCA +:10088000FF1FE80FF91FE35BFD4F808186FFC9CF93 +:10089000E0912A018E2FEE0F990BFC01EE0FFF1F46 +:1008A000E80FF91FE35BFD4F808160E08F730E94CA +:1008B000CB01B7CF2091840030918500E0912A01CF +:1008C0008E2FEE0F990BFC01EE0FFF1FE80FF91FA3 +:1008D000E35BFD4F81819281820F931F909389008A +:1008E00080938800E0912A018E2FEE0F990BFC0176 +:1008F000EE0FFF1FE80FF91FE35BFD4F808186FFBE +:1009000011C0E0912A018E2FEE0F990BFC01EE0F22 +:10091000FF1FE80FF91FE35BFD4F808161E08F73DC +:100920000E94CB01FF91EF91DF91CF91BF91AF91E9 +:100930009F918F917F916F915F914F913F912F91F7 +:100940000F900FBE0F901F90189580E49CE9909334 +:100950008900809388008FEF80932A01E3CFCF92A4 +:10096000DF92EF92FF920F931F93E82FF92F05C0AC +:10097000015011092109310961F1908196239417E1 +:10098000B9F305C0015011092109310911F1908114 +:1009900096239413F7CFC12CD12CE12CF12C0AC053 +:1009A0008FEFC81AD80AE80AF80A0C151D052E059B +:1009B0003F0579F080818623841791F36C2D7D2D7E +:1009C0008E2D9F2D1F910F91FF90EF90DF90CF9074 +:1009D000089560E070E080E090E01F910F91FF903B +:1009E000EF90DF90CF9008951092B3011092B20172 +:1009F00088EE93E0A0E0B0E08093B4019093B5015D +:100A0000A093B601B093B70185E191E09093B10155 +:100A10008093B00185EC90E09093BD018093BC0180 +:100A200084EC90E09093BF018093BE0180EC90E055 +:100A30009093C1018093C00181EC90E09093C30139 +:100A40008093C20182EC90E09093C5018093C40131 +:100A500086EC90E09093C7018093C6011092C90183 +:100A60001092CA011092CB011092CC01E2E7F2E0A1 +:100A70002AE832E04FEF68EB7BE0809171028C3026 +:100A8000B0F491E0980F90937102808390E0DC01C4 +:100A9000AA0FBB1FA80FB91FA35BBD4F12967C9373 +:100AA0006E93119733962E173F0739F708954083B9 +:100AB000F9CFCF93DF9300D000D0CDB7DEB77894D5 +:100AC00084B5826084BD84B5816084BD85B5826053 +:100AD00085BD85B5816085BD80916E008160809304 +:100AE0006E0010928100809181008260809381006D +:100AF000809181008160809381008091800081607D +:100B0000809380008091B10084608093B1008091D7 +:100B1000B00081608093B00080917A0084608093FF +:100B20007A0080917A00826080937A0080917A00C6 +:100B3000816080937A0080917A00806880937A0047 +:100B40001092C100E091C001F091C10182E0808368 +:100B5000E091BC01F091BD011082E091BE01F091E5 +:100B6000BF0180E180831092C801E091C401F0913F +:100B7000C50186E08083E091C201F091C3018081CC +:100B800080618083E091C201F091C301808188601F +:100B90008083E091C201F091C301808180688083ED +:100BA000E091C201F091C30180818F7D8083198221 +:100BB00061E089810E94250260E089810E94CB0169 +:100BC00029812F5F29832E3099F768EC70E080E04F +:100BD00090E00E947B0222242394312C80EB91E050 +:100BE0000E94F3009A838983892B09F454C480EB13 +:100BF00091E00E94F3001816190684F780EB91E04B +:100C00000E94D10090918E01853509F065C0911147 +:100C100063C080918D018F3F29F431E030938C01C6 +:100C200030938E0180918C018F5F843308F06CC00B +:100C300080938C0180918E01882381F280918B01B9 +:100C40008111CCCF80918C01843040F210928E01C2 +:100C500020915C01D0905D01ED2CF12C30915B0175 +:100C6000323009F486C0333009F4A3C0313089F53D +:100C7000273009F06BC080915E01898390E020915C +:100C80009301211146C030939301F0920401E09248 +:100C900003019093020180930101F701EE0FFF1F02 +:100CA000EC56FE4F31822082880F991FFC01EC56D2 +:100CB000FE4F3182208261E08D2D0E94250260E08E +:100CC00089810E94250262E370E080E090E00E944A +:100CD0007B0210928C0182CF80938D01992309F4BD +:100CE000A1CFE0918C01E23039F480938B01F0E0E8 +:100CF000E95AFE4F808396CFE330C8F390918B0181 +:100D0000915090938B01F3CF10928C0110928E0131 +:100D100091CF409103015091040120910101309144 +:100D20000201E416F50619F42817390791F2440F69 +:100D3000551FFA01EC56FE4F11821082220F331F0D +:100D4000F901EC56FE4F118210829FCFC701880F28 +:100D5000991F1092930110928F011092900110929E +:100D60009101109292018C569E4FFC0111821082CB +:100D7000B0CF8091030190910401E816F90639F093 +:100D80008091010190910201E816F90651F4109248 +:100D9000930110928F011092900110929101109284 +:100DA0009201243009F4ACC23CF42130B1F023307C +:100DB000E9F00E94C3028DCF253009F478C02830B5 +:100DC000C1F72FB7F8948091530190915401A091ED +:100DD0005501B09156012FBFECCFC7010E94AD0263 +:100DE00060915E018D2D0E94CB01E3CFC7010E946F +:100DF000AD02F0915E01F98361E08D2D0E94250224 +:100E00002981211102C060E0EDCF39813F3F11F40B +:100E100061E0E8CFF701E358FF4FE491E33041F19F +:100E200040F4E130C9F0E230E9F0E981E7FDF0CFCC +:100E3000EACFE73051F1E83089F1E430B1F7809141 +:100E400080008062809380003981232F30E03093CE +:100E50008B0020938A00ADCF84B5806884BD8981E2 +:100E600087BDA7CF84B5806284BD998198BDA1CF8D +:100E700080918000806880938000F981EF2FF0E0FE +:100E8000F0938900E093880094CF8091B00080684F +:100E90008093B00089818093B3008BCF8091B000A4 +:100EA00080628093B00099819093B40082CFC70193 +:100EB0000E94AD0280915E018093300180915F01BC +:100EC0008093310120913001309131013C832B839B +:100ED00080916001809330018091610180933101A4 +:100EE00080913001909131019A83898318161906F7 +:100EF0000CF002C2809100018D11CDC0ECE7F0E052 +:100F0000149117FD56CF61E08D2D0E94250211230B +:100F1000B1F02B813C814901B12CA12C60E072E140 +:100F20008AE790E0A5010E94900C69017A0181E0B6 +:100F3000C81AD108E108F108123009F09AC1EB8112 +:100F4000FC814F01B12CA12C60E072E18AE790E0B6 +:100F5000A5019F010E94900C29013A017A016901C3 +:100F6000F1E0CF1AD108E108F1082FEFC216D10441 +:100F7000E104F10409F00CF44FC160E472E48FE085 +:100F800090E0A50194010E94900C69017A0181E032 +:100F9000C81AD108E108F108123009F0F4C082E063 +:100FA0009FEFC916D104E104F10409F00CF46CC000 +:100FB00060E970ED83E090E0A50194010E94900C3F +:100FC00069017A01E1E0CE1AD108E108F10883E075 +:100FD000FFEFCF16D104E104F10409F00CF454C082 +:100FE00068E478EE81E090E0A50194010E94900C05 +:100FF00069017A0181E0C81AD108E108F10884E0AA +:101000009FEFC916D104E104F104F1F1ECF164E2BF +:1010100074EF80E090E0A50194010E94900C6901BA +:101020007A0191E0C91AD108E108F10885E03FEFA3 +:10103000C316D104E104F10439F130F162E17AE739 +:1010400080E090E0A50194010E94900C69017A0172 +:10105000E1E0CE1AD108E108F10886E0FFEFCF16F3 +:10106000D104E104F10481F078F0730162012AE017 +:10107000F594E794D794C7942A95D1F721E0C21A42 +:10108000D108E108F10887E09091B100987F892BA1 +:101090008093B100C8C08F3F09F08BCED092000181 +:1010A000ECE7F0E014911F3F09F483CE113031F1E9 +:1010B00050F0123009F442C017FD7BCE61E08D2D57 +:1010C0000E94250226CF14BC15BC84B5826084BD65 +:1010D00085B5816085BDF701E556FF4FE491F0E0ED +:1010E000EE0FFF1FEE58FF4F85919491F701E155E8 +:1010F000FF4FE491E093360110E005CF109280009D +:10110000109281008091810088608093810080919D +:101110008100816080938100F701E556FF4FE491E3 +:10112000F0E0EE0FFF1FEE58FF4F85919491F7010D +:10113000E155FF4FE491E0933501E5CE1092B00008 +:101140001092B1008091B00082608093B0008091D5 +:10115000B10081608093B100F701E556FF4FE49143 +:10116000F0E0EE0FFF1FEE58FF4F859194919093A2 +:10117000340180933301F701E155FF4FE491E0938F +:10118000320112E0C0CE2FEFC216D104E104F10407 +:1011900009F00CF46CC068E478EE81E090E0A50101 +:1011A00094010E94900C69017A0181E0C81AD1086B +:1011B000E108F10884E011113ACF83E02FEFC21665 +:1011C000D104E104F10459F154F162E17AE780E0DD +:1011D00090E0A50194010E94900C69017A01E1E080 +:1011E000CE1AD108E108F10884E0FFEFCF16D10450 +:1011F000E104F104A1F098F0730162019AE0F59422 +:10120000E794D794C7949A95D1F731E0C31AD108DF +:10121000E108F10885E003C081E0111135CF95B5F3 +:10122000987F892B85BD2B813C81220F331FA9819B +:10123000BA810E945D0D28EE33E040E050E00E944C +:10124000BA0C1130B9F1123009F446C01111B1CD08 +:10125000C7BC20933F01309340014093410150931C +:10126000420180916E00826080936E00A2CD82E088 +:10127000D4CF91E0C114D10421E0E206F10484F05E +:1012800068E478EE81E090E0A50194010E94900C62 +:1012900069017A0181E0C81AD108E108F10893E0F8 +:1012A000113009F0C0CF80918100887F892B809315 +:1012B0008100B9CFD0928900C092880020933B0171 +:1012C00030933C0140933D0150933E0180916F006B +:1012D000826080936F006DCDC092B3002093370180 +:1012E000309338014093390150933A018091700056 +:1012F0008260809370005DCD8D2D0E94F90159CDE3 +:10130000C7010E94AD0200915E01053B08F051CD7E +:10131000E3E4F1E090E080E021913191E216F30600 +:1013200051F0232B09F0AFC0FC01EE0FFF1FED5B66 +:10133000FE4FF182E0829C01220F331F820F931F28 +:10134000FC01EE58FD4F1081818192811C3008F024 +:101350003FC061E08D2D0E942502812F90E0AC01FD +:10136000440F551FFA01E80FF91FE35BFD4F2D2DC8 +:101370002F73D22E2081207CD22AD08230E020E030 +:10138000F901EE0FFF1FE20FF31FE35BFD4F6081DA +:1013900066FD14C02F5F3F4F2C30310589F7109246 +:1013A000800022E02093810010928500109284003A +:1013B000B19A20916F00226020936F00840F951FD7 +:1013C000FC01E35BFD4F80818064808390E080E0DE +:1013D0001C3008F0EECCE8E5EE2EE2E0FE2EE91A35 +:1013E000F10897FDF394EE0CFF1CEE0CFF1CE8E8EF +:1013F000F0E0E81BF10987FDF395EE0FFF1FEE0FFC +:10140000FF1FFA83E9834F01FF0FAA08BB0897016A +:101410000F2C000C440B550B281939094A095B099C +:10142000A02FB0E00E94AF0C24EB30E040E050E091 +:101430000E94900C820E931EA41EB51E29813A8133 +:10144000821693063CF0FA82E9828E149F0414F40B +:101450009A82898289819A810297880F991F9A833B +:1014600089834FB7F894212F30E0C901880F991F65 +:10147000820F931FFC01E35BFD4F29813A81328388 +:1014800021834FBF96CC01968830910509F044CF57 +:1014900090E080E050CF6FE070E080E090E00E944C +:1014A0007B0254E9E52E51E0F52EF70101911191EF +:1014B0007F010115110509F03DC0B98060E08B2D59 +:1014C0000E9425020E94EF02E981FA81E358FF4F52 +:1014D0008491E981FA81E155FF4FC490E981FA8155 +:1014E000E556FF4FD490DD2099F081110E94A201B2 +:1014F000ED2DF0E0EE0FFF1FEF56FF4FA591B491D9 +:10150000EC91CE2291E080E009F490E0092F182FB1 +:10151000B801110F880B990B0E94730B0E94CB022C +:101520008B2D0E94BE0281E00E94BE020E94BA0082 +:101530000E94C30229813A812F5F3F4F3A8329835A +:101540002E30310509F0B1CF85E091E09A8389838F +:1015500010E0E981FA8181919191FA83E983892BE5 +:1015600039F50E94EF02812F806480937C00809186 +:101570007A00806480937A0080917A0086FDFCCFA7 +:101580008091780060917900762F682F072E000CEB +:10159000880B990B0E94730B0E94CB02812F0E9433 +:1015A000BE0282E00E94BE020E94BA000E94C302F4 +:1015B0001F5F163071F680919301882309F470C083 +:1015C000F0910301F98360E08F2F0E94CB0183E04B +:1015D00090E00197F1F761E089810E94CB0183E2FD +:1015E00090E00197F1F760E089810E94CB01809142 +:1015F0000101909102019927FC01E155FF4F64918F +:10160000FC01E556FF4FE491F0E0EE0FFF1FEF56AF +:10161000FF4F8591949100E315E720E030E0462FDD +:101620000E94AF04611571058105910529F06F5F76 +:101630007F4F8F4F9F4F9F700E94710B20E030E0D3 +:1016400048EE51E40E94EB0C20E030E040E05FE324 +:101650000E94D20B6B017C0120E030E0A9010E94C6 +:101660006C0B811130C0C0908F01D0909001E09040 +:101670009101F09092010E94EF02C701B6010E9411 +:10168000CB02809103010E94BE02809101010E9461 +:10169000BE0287E00E94BE020E94BA000E94C302FE +:1016A0006AE070E080E090E00E947B0280E090E0E1 +:1016B000892B09F490CA0E94FF00882309F48BCA81 +:1016C0000E94000088CAC0928F01D0929001E092DF +:1016D0009101F0929201CFCF0E94AE0B08F481E00D +:1016E0000895E89409C097FB3EF490958095709515 +:1016F00061957F4F8F4F9F4F9923A9F0F92F96E95E +:10170000BB279395F695879577956795B795F111D2 +:10171000F8CFFAF4BB0F11F460FF1BC06F5F7F4F6F +:101720008F4F9F4F16C0882311F096E911C0772381 +:1017300021F09EE8872F762F05C0662371F096E88A +:10174000862F70E060E02AF09A95660F771F881F59 +:10175000DAF7880F9695879597F90895990F0008FD +:10176000550FAA0BE0E8FEEF16161706E807F90773 +:10177000C0F012161306E407F50798F0621B730B0E +:10178000840B950B39F40A2661F0232B242B252B8F +:1017900021F408950A2609F4A140A6958FEF811D32 +:1017A000811D08950E94E50B0C94560C0E94480C74 +:1017B00038F00E944F0C20F0952311F00C943F0C50 +:1017C0000C94450C11240C948A0C0E94670C70F345 +:1017D000959FC1F3950F50E0551F629FF001729FD6 +:1017E000BB27F00DB11D639FAA27F00DB11DAA1FE5 +:1017F000649F6627B00DA11D661F829F2227B00D32 +:10180000A11D621F739FB00DA11D621F839FA00DBC +:10181000611D221F749F3327A00D611D231F849F0C +:10182000600D211D822F762F6A2F11249F57504063 +:101830009AF0F1F088234AF0EE0FFF1FBB1F661FDE +:10184000771F881F91505040A9F79E3F510580F0A7 +:101850000C943F0C0C948A0C5F3FE4F3983ED4F355 +:10186000869577956795B795F795E7959F5FC1F74B +:10187000FE2B880F911D9695879597F9089597F9F6 +:101880009F6780E870E060E008959FEF80EC089526 +:1018900000240A941616170618060906089500244F +:1018A0000A9412161306140605060895092E0394C9 +:1018B000000C11F4882352F0BB0F40F4BF2B11F43D +:1018C00060FF04C06F5F7F4F8F4F9F4F089557FD9C +:1018D0009058440F551F59F05F3F71F04795880F9E +:1018E00097FB991F61F09F3F79F087950895121635 +:1018F00013061406551FF2CF4695F1DF08C01616E1 +:1019000017061806991FF1CF869571056105089491 +:101910000895E894BB2766277727CB0197F90895A8 +:10192000052E97FB1EF400940E94A70C57FD07D0CC +:101930000E94BA0C07FC03D04EF40C94A70C5095EF +:101940004095309521953F4F4F4F5F4F08959095AB +:101950008095709561957F4F8F4F9F4F08950E949E +:10196000DC0CA59F900DB49F900DA49F800D911D40 +:1019700011240895A1E21A2EAA1BBB1BFD010DC064 +:10198000AA1FBB1FEE1FFF1FA217B307E407F5072F +:1019900020F0A21BB30BE40BF50B661F771F881F0B +:1019A000991F1A9469F760957095809590959B01A1 +:1019B000AC01BD01CF010895A29FB001B39FC0014A +:1019C000A39F700D811D1124911DB29F700D811D6B +:1019D0001124911D08950E94FF0C0C94560C0E9436 +:1019E0004F0C58F00E94480C40F029F45F3F29F05A +:1019F0000C943F0C51110C948A0C0C94450C0E94D1 +:101A0000670C68F39923B1F3552391F3951B550B9C +:101A1000BB27AA2762177307840738F09F5F5F4FC1 +:101A2000220F331F441FAA1FA9F335D00E2E3AF000 +:101A3000E0E832D091505040E695001CCAF72BD018 +:101A4000FE2F29D0660F771F881FBB1F2617370769 +:101A50004807AB07B0E809F0BB0B802DBF01FF279B +:101A600093585F4F3AF09E3F510578F00C943F0C2D +:101A70000C948A0C5F3FE4F3983ED4F386957795F7 +:101A80006795B795F7959F5FC9F7880F911D969554 +:101A9000879597F90895E1E0660F771F881FBB1FB0 +:101AA000621773078407BA0720F0621B730B840B5D +:101AB000BA0BEE1F88F7E09508950E94DC0CB7FF83 +:101AC0000895821B930B0895EE0FFF1F0590F4916C +:081AD000E02D0994F894FFCF0A +:101AD800FF0C000D000000000000000000000000E6 +:101AE800000000000035018D00C2008201F300D122 +:061AF80000E5000D0A00EC +:00000001FF diff --git a/app/modules/aiot.json b/app/modules/aiot.json index d1549bee1..07a81e74d 100644 --- a/app/modules/aiot.json +++ b/app/modules/aiot.json @@ -1,27 +1,27 @@ { - "id": "260201", - "name": { - "ko": "AIoT 보드", - "en": "AIoT Board" - }, - "category": "board", - "platform": ["win32", "darwin"], - "icon" : "aiot.png", - "module": "aiot.js", - "url": "http://wonn.co.kr", - "email": "wonn@wonn.co.kr", - "driver": { - "win32-ia32": "CDM21226_Setup/CDM21226_Setup.exe", - "win32-x64": "CDM21226_Setup/CDM21226_Setup.exe" - }, - "reconnect" : true, - "firmware": "aiot", - "hardware": { - "type": "serial", - "control": "slave", - "duration": 32, - "vendor": ["Arduino", "wch.cn", "FTDI"], - "baudRate": 115200, - "firmwarecheck" : false - } + "id": "260201", + "name": { + "ko": "아두이노 확장 쉴드", + "en": "Arduino Extension Shield" + }, + "category": "board", + "platform": ["win32", "darwin"], + "icon": "aiot.png", + "module": "aiot.js", + "email": "cowboy0125@naver.com", + "driver": { + "win32-ia32": "CDM21226_Setup/CDM21226_Setup.exe", + "win32-x64": "CDM21226_Setup/CDM21226_Setup.exe" + }, + "selectPort": true, + "reconnect": true, + "firmware": "aiot", + "hardware": { + "type": "serial", + "control": "slave", + "duration": 32, + "vendor": ["Arduino", "wch.cn", "FTDI"], + "baudRate": 115200, + "firmwarecheck": false + } } diff --git a/app/modules/aiot.png b/app/modules/aiot.png index cd7df7d23..af14ac0e3 100644 Binary files a/app/modules/aiot.png and b/app/modules/aiot.png differ diff --git a/app/modules/c3coding_arduino.js b/app/modules/c3coding_arduino.js new file mode 100644 index 000000000..81e8692dc --- /dev/null +++ b/app/modules/c3coding_arduino.js @@ -0,0 +1,451 @@ +const BaseModule = require('./baseModule'); + +class c3coding_arduino extends BaseModule { + // 클래스 내부에서 사용될 필드들을 이곳에서 선언합니다. + constructor() { + super(); + + this.sp = null; + this.sensorTypes = { + ALIVE: 0, + DIGITAL: 1, + ANALOG: 2, + PWM: 3, + SERVO_PIN: 4, + TONE: 5, + PULSEIN: 6, + ULTRASONIC: 7, + TIMER: 8, + }; + + this.actionTypes = { + GET: 1, + SET: 2, + RESET: 3, + }; + + this.sensorValueSize = { + FLOAT: 2, + SHORT: 3, + }; + + this.digitalPortTimeList = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + + this.sensorData = { + ULTRASONIC: 0, + DIGITAL: { + '0': 0, + '1': 0, + '2': 0, + '3': 0, + '4': 0, + '5': 0, + '6': 0, + '7': 0, + '8': 0, + '9': 0, + '10': 0, + '11': 0, + '12': 0, + '13': 0, + }, + ANALOG: { + '0': 0, + '1': 0, + '2': 0, + '3': 0, + '4': 0, + '5': 0, + }, + PULSEIN: {}, + TIMER: 0, + }; + + this.defaultOutput = {}; + this.recentCheckData = {}; + this.sendBuffers = []; + this.lastTime = 0; + this.lastSendTime = 0; + this.isDraing = false; + this.sensorIdx = 0; + }; + + /* + 최초에 커넥션이 이루어진 후의 초기 설정. + handler 는 워크스페이스와 통신하 데이터를 json 화 하는 오브젝트입니다. (datahandler/json 참고) + config 은 module.json 오브젝트입니다. + */ + init(handler, config) { + this.handler = handler; + this.config = config; + } + setSerialPort = function (sp) { + var self = this; + this.sp = sp; + }; + // 연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다.(필수) + requestInitialData = function () { + return this.makeSensorReadBuffer(this.sensorTypes.ANALOG, 0); + }; + // 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다.(필수) + checkInitialData = function (data, config) { + return true; + }; + afterConnect = function (that, cb) { + that.connected = true; + if (cb) { + cb('connected'); + } + }; + // optional. 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다. + validateLocalData = function (data) { + return true; + }; + /** 엔트리에 데이터 전송하기 + * Web Socket(엔트리)에 아날로그, 디지털등 데이터 전송 + * @param handler + */ + requestRemoteData = function (handler) { + var self = this; + if (!self.sensorData) { + return; + } + Object.keys(this.sensorData).forEach(function (key) { + if (self.sensorData[key] != undefined) { + handler.write(key, self.sensorData[key]); + } + }); + }; + // 엔트리에서 받은 데이터에 대한 처리 + handleRemoteData = function (handler) { + var self = this; + var getDatas = handler.read('GET'); + var setDatas = handler.read('SET') || this.defaultOutput; + var time = handler.read('TIME'); + var buffer = new Buffer([]); + + if (getDatas) { + var keys = Object.keys(getDatas); + keys.forEach(function (key) { + var isSend = false; + var dataObj = getDatas[key]; + if ( + typeof dataObj.port === 'string' || + typeof dataObj.port === 'number' + ) { + var time = self.digitalPortTimeList[dataObj.port]; + if (dataObj.time > time) { + isSend = true; + self.digitalPortTimeList[dataObj.port] = dataObj.time; + } + } else if (Array.isArray(dataObj.port)) { + isSend = dataObj.port.every(function (port) { + var time = self.digitalPortTimeList[port]; + return dataObj.time > time; + }); + + if (isSend) { + dataObj.port.forEach(function (port) { + self.digitalPortTimeList[port] = dataObj.time; + }); + } + } + + if (isSend) { + if (!self.isRecentData(dataObj.port, key, dataObj.data)) { + self.recentCheckData[dataObj.port] = { + type: key, + data: dataObj.data, + }; + buffer = Buffer.concat([ + buffer, + self.makeSensorReadBuffer( + key, + dataObj.port, + dataObj.data + ), + ]); + } + } + }); + } + + if (setDatas) { + var setKeys = Object.keys(setDatas); + setKeys.forEach(function (port) { + var data = setDatas[port]; + if (data) { + if (self.digitalPortTimeList[port] < data.time) { + self.digitalPortTimeList[port] = data.time; + + if (!self.isRecentData(port, data.type, data.data)) { + self.recentCheckData[port] = { + type: data.type, + data: data.data, + }; + buffer = Buffer.concat([ + buffer, + self.makeOutputBuffer(data.type, port, data.data), + ]); + } + } + } + }); + } + + if (buffer.length) { + this.sendBuffers.push(buffer); + } + }; + /** + * 기존에 수신했던 데이터인가 + * 기존에 수신했던 데이터인지 확인합니다. 예를들어 LED ON/OFF의 경우 무한루프에서 상태가 변하지 않을 경우 추가로 신호를 하드웨어에 보내서 불필요한 오버헤드를 + * 발생시킬 필요가 없으므로, 같은 신호에 대해서는 중복으로 보내지 않도록 만듭니다. + * 하지만, Tone과 같이 같은 신호라도 출력데이터를 보내야하므로 별도의 예외처리가 필요합니다. + * @param port + * @param type + * @param data + * @returns {boolean} + */ + isRecentData = function (port, type, data) { + var that = this; + var isRecent = false; + + if (type == this.sensorTypes.ULTRASONIC) { + var portString = port.toString(); + var isGarbageClear = false; + Object.keys(this.recentCheckData).forEach(function (key) { + var recent = that.recentCheckData[key]; + if (key === portString) { + + } + if (key !== portString && recent.type == that.sensorTypes.ULTRASONIC) { + delete that.recentCheckData[key]; + isGarbageClear = true; + } + }); + + if ((port in this.recentCheckData && isGarbageClear) || !(port in this.recentCheckData)) { + isRecent = false; + } else { + isRecent = true; + } + + } else if (port in this.recentCheckData && type != this.sensorTypes.TONE) { + if ( + this.recentCheckData[port].type === type && + this.recentCheckData[port].data === data + ) { + isRecent = true; + } + } + + return isRecent; + }; + /** + * 송신(PC->하드웨어) 데이터 + * 시리얼통신으로 버퍼에 쌓아놓은 데이터를 전송합니다. + * @returns {null} + */ + requestLocalData = function () { + var self = this; + + if (!this.isDraing && this.sendBuffers.length > 0) { + this.isDraing = true; + this.sp.write(this.sendBuffers.shift(), function () { + if (self.sp) { + self.sp.drain(function () { + self.isDraing = false; + }); + } + }); + } + + return null; + }; + /** 수신(하드웨어->PC) 데이터 처리 + *ff 55 idx size data a + */ + handleLocalData = function (data) { + var self = this; + var datas = this.getDataByBuffer(data); + + datas.forEach(function (data) { + if (data.length <= 4 || data[0] !== 255 || data[1] !== 85) { + return; + } + var readData = data.subarray(2, data.length); + var value; + switch (readData[0]) { + case self.sensorValueSize.FLOAT: { + value = new Buffer(readData.subarray(1, 5)).readFloatLE(); + value = Math.round(value * 100) / 100; + break; + } + case self.sensorValueSize.SHORT: { + value = new Buffer(readData.subarray(1, 3)).readInt16LE(); + break; + } + default: { + value = 0; + break; + } + } + + var type = readData[readData.length - 1]; + var port = readData[readData.length - 2]; + + switch (type) { + case self.sensorTypes.DIGITAL: { + self.sensorData.DIGITAL[port] = value; + break; + } + case self.sensorTypes.ANALOG: { + self.sensorData.ANALOG[port] = value; + break; + } + case self.sensorTypes.PULSEIN: { + self.sensorData.PULSEIN[port] = value; + break; + } + case self.sensorTypes.ULTRASONIC: { + self.sensorData.ULTRASONIC = value; + break; + } + case self.sensorTypes.TIMER: { + self.sensorData.TIMER = value; + break; + } + default: { + break; + } + } + }); + }; + makeSensorReadBuffer = function (device, port, data) { + var buffer; + var dummy = new Buffer([10]); + if (device == this.sensorTypes.ULTRASONIC) { + buffer = new Buffer([ + 255, + 85, + 6, + this.sensorIdx, + this.actionTypes.GET, + device, + port[0], + port[1], + 10, + ]); + } else if (!data) { + buffer = new Buffer([ + 255, + 85, + 5, + this.sensorIdx, + this.actionTypes.GET, + device, + port, + 10, + ]); + } else { + value = new Buffer(2); + value.writeInt16LE(data); + buffer = new Buffer([ + 255, + 85, + 7, + this.sensorIdx, + this.actionTypes.GET, + device, + port, + 10, + ]); + buffer = Buffer.concat([buffer, value, dummy]); + } + this.sensorIdx++; + if (this.sensorIdx > 254) { + this.sensorIdx = 0; + } + return buffer; + }; + /** 전송(PC->하드웨어) 버퍼 만들기 + * 0xff 0x55 0x6 0x0 0x1 0xa 0x9 0x0 0x0 0xa + */ + makeOutputBuffer = function (device, port, data) { + var buffer; + var value = new Buffer(2); + var dummy = new Buffer([10]); + switch (device) { + case this.sensorTypes.SERVO_PIN: + case this.sensorTypes.DIGITAL: + case this.sensorTypes.PWM: { + value.writeInt16LE(data); + buffer = new Buffer([ + 255, + 85, + 6, + this.sensorIdx, + this.actionTypes.SET, + device, + port, + ]); + buffer = Buffer.concat([buffer, value, dummy]); + break; + } + case this.sensorTypes.TONE: { + var time = new Buffer(2); + if ($.isPlainObject(data)) { + value.writeInt16LE(data.value); + time.writeInt16LE(data.duration); + } else { + value.writeInt16LE(0); + time.writeInt16LE(0); + } + buffer = new Buffer([ + 255, + 85, + 8, + this.sensorIdx, + this.actionTypes.SET, + device, + port, + ]); + buffer = Buffer.concat([buffer, value, time, dummy]); + break; + } + case this.sensorTypes.TONE: { + } + } + + return buffer; + }; + getDataByBuffer = function (buffer) { + var datas = []; + var lastIndex = 0; + buffer.forEach(function (value, idx) { + if (value == 13 && buffer[idx + 1] == 10) { + datas.push(buffer.subarray(lastIndex, idx)); + lastIndex = idx + 2; + } + }); + + return datas; + }; + // 하드웨어 연결 해제 시 호출됩니다. + disconnect = function (connect) { + var self = this; + connect.close(); + if (self.sp) { + delete self.sp; + } + }; + // 엔트리와의 연결 종료 후 처리 코드입니다. + reset = function () { + this.lastTime = 0; + this.lastSendTime = 0; + + this.sensorData.PULSEIN = {}; + }; +} +module.exports = new c3coding_arduino(); \ No newline at end of file diff --git a/app/modules/c3coding_arduino.json b/app/modules/c3coding_arduino.json new file mode 100644 index 000000000..7071d6dde --- /dev/null +++ b/app/modules/c3coding_arduino.json @@ -0,0 +1,37 @@ +{ + "id": "5C0101", + "name": { + "en": "C3Coding Arduino", + "ko": "씨큐브코딩 아두이노" + }, + "category": "board", + "platform": [ + "win32", + "darwin" + ], + "icon": "c3coding_arduino.png", + "module": "c3coding_arduino.js", + "driver": { + "win32-ia32": "arduino/dpinst-x86.exe", + "win32-x64": "arduino/dpinst-amd64.exe" + }, + "url": "https://www.c3coding.com/", + "reconnect": true, + "firmware": "c3coding_arduino", + "hardware": { + "type": "serial", + "control": "slave", + "duration": 32, + "vendor": [ + "Arduino", + "wch.cn", + "FTDI" + ], + "baudRate": 115200, + "firmwarecheck": false, + "byteDelimiter": [ + 13, + 10 + ] + } +} \ No newline at end of file diff --git a/app/modules/c3coding_arduino.png b/app/modules/c3coding_arduino.png new file mode 100644 index 000000000..17e9988a1 Binary files /dev/null and b/app/modules/c3coding_arduino.png differ diff --git a/app/modules/hexaboard.js b/app/modules/hexaboard.js new file mode 100644 index 000000000..f56e53462 --- /dev/null +++ b/app/modules/hexaboard.js @@ -0,0 +1,729 @@ +// const _ = global.$; +const BaseModule = require('./baseModule'); +const { forEach } = require('lodash'); +// const { forEach } = require('lodash'); + +class hexaboard extends BaseModule { + constructor() { + super(); + this.counter = 0; + this.commandResponseSize = 8; + this.wholeResponseSize = 0x32; + this.isSendInitData = false; + this.isSensorCheck = false; + this.isConnect = false; + + this.sp = null; + this.sendBuffers = []; + this.recvBuffers = []; // 수신 데이터를 저장할 버퍼 + + this.sensors = []; + this.sensorDatas = { + '35' : 0, //BUTTON_A + '34' : 0, //BUTTON_B + '32' : 0, //PIN_1 + '33' : 0, //PIN_2 + '4' : 0, //PIN_3 + 'A32' : 0, //PIN_1 + 'A33' : 0, //PIN_2 + 'A4' : 0, //PIN_3 + 'C0' : 0, //RED + 'C1' : 0, //GREEN + 'C2' : 0, //BLUE + 'C3' : 0, //WHITHE + '11' : 0, //LEFT + '12' : 0, //RIGHT + '13' : 0, //FRONT + '14' : 0, //BACK + '15' : 0, //UP + '16' : 0, //DOWN + 'A17' : 0, //ANGLE_X + 'A18' : 0, //ANGLE_Y + 'A19' : 0, //ANGLE_Z + 'D0' : 0, //HUMI + 'D1' : 0, //TEMP + 'BC' : 0, //BLYNK CONNECTED + 'V0' :0, + 'V1' :0, + 'V2' :0, + 'V3' :0, + 'V4' :0, + 'V5' :0, + 'V6' :0, + 'V7' :0, + 'V8' :0, + 'V9' :0, + 'V10' :0, + 'V11' :0, + 'V12' :0, + 'V13' :0, + 'V14' :0, + 'V15' :0, + 'V16' :0, + 'V17' :0, + 'V18' :0, + 'V19' :0, + 'V20' :0, + }; + this.returnData = { + + }; + + /** + * HEXABOARD 관려 내용들 추후 아래 모두 삭제 + */ + this.sensorTypes = { + DIGITAL_WRITE: 0x01, // 디지털 출력 변경 + ANALOG_WRITE: 0x02, // PWM을 이용한 아날로그 출력 변경 + DIGITAL_READ: 0x03, // 디지털 입력 상태 요청 + ANALOG_READ: 0x04, // 아날로그 입력 값 요청 + PLAY_TONE: 0x05, // 부저에 음 재생 + READ_COLOR_SENSOR: 0x06, // 색상 센서 값 요청 (R,G,B,W) + READ_GYRO_SENSOR: 0x07, // 자이로 센서 값 요청 + READ_GYRO_ANGLE_SENSOR: 0x17, // 자이로 센서 값 요청 + READ_DHT_SENSOR : 0x13, //DHT11 센서 값 + UPDATE_NEOPIXEL: 0x08, // 네오픽셀 LED 상태 변경 + SLIDE_NEOPIXEL: 0x09, //네오픽셀 텍스트 출력 + DISPLAY_OLED: 0x10, // OLED 값 정의 + DISPLAY_INIT_OLED: 0x12, // OLED 값 정의 + UPDATE_ALL_NEOPIXEL: 0x11, //모든 네오픽셀 켜기 + CONNECT_WIFI: 0x21, //WIFI 연결 + CONNECT_BLYNK: 0x21, //BLYNK서버 연결 + BLYNK_VIRTUAL_WRITE: 0x22, //BLYNK 가상의 핀 데이터 전송 + BLYNK_WRITE: 0x23, //BLYNK 상태값 바뀌었을때 + CONNECTED_BLYNK: 0x24, //BLYNK 연결 상태 확인 + }; + // 자이로 센서에 대한 추가적인 세부 명령 정의 + this.gyro_sensor = { + LEFT: 0x11, + RIGHT: 0x12, + FRONT: 0x13, + BACK: 0x14, + UP: 0x15, + DOWN: 0x16, + ANGLE_X: 0x17, + ANGLE_Y: 0x18, + ANGLE_Z: 0x19, + }; + this.command = { + READ: 1, + WRITE: 0, + }; + } + + hexColorToRgb(hexColor) { + // '#FF0000' 형식의 색상 코드를 'FF0000'으로 변환 + // console.log(hexColor); + const color = hexColor.replace('#', ''); + + // R, G, B 값을 16진수에서 10진수로 변환 + const r = parseInt(color.substring(0, 2), 16); + const g = parseInt(color.substring(2, 4), 16); + const b = parseInt(color.substring(4, 6), 16); + + return [r, g, b]; + } + + // 이 아래로는 자유롭게 선언하여 사용한 함수입니다. + makeOutputBuffer(options = {}) { + const { + command = 0x00, + sensorType = 0x00, + pin = 0x00, + duration = 0x00, + data = 0, + message = '', + message2 = '', + color = '', + } = options; + let buffer; + const value = new Buffer(2); + value.writeInt16LE(data); + + // 데이터 사이즈 : header 2 + length 1 + command 1 + type 1 + port 1 + duration 1 +data(2) + dummy + let dataLength = 10; + const dummy = new Buffer([10]); + let messageBuffer = Buffer.alloc(0); + let colorBuffer = Buffer.alloc(0); + + if (message) { + messageBuffer = Buffer.from(message, 'utf8'); + dataLength += messageBuffer.length; + // console.log(messageBuffer); + } + + if (color) { + const rgbValues = this.hexColorToRgb(color); + colorBuffer = Buffer.from(rgbValues); + dataLength += colorBuffer.length; // 컬러 데이터 길이 추가 + // console.log(`dataLength ${dataLength} 에 추가 + ${colorBuffer.length}`); + } + + if (dataLength > 256) { + // 에러 처리 또는 데이터 분할 필요 + throw new Error('Data length exceeds buffer limit'); + } + + buffer = new Buffer([ + 255, + 85, + dataLength, + command, + sensorType, + pin, + duration, + ]); + buffer = Buffer.concat([buffer, value, colorBuffer, messageBuffer, dummy]); + + return buffer; + }; + + makeOutputWifiBuffer(options = {}) { + const { + command = 0x00, + sensorType = 0x00, + ssid = '', + password = '', + auth = '', + } = options; + const dummy = new Buffer([10]); + + const ssidBuffer = ssid ? Buffer.from(ssid, 'utf8') : Buffer.alloc(0); + const passwordBuffer = password ? Buffer.from(password, 'utf8') : Buffer.alloc(0); + const authBuffer = auth ? Buffer.from(auth, 'utf8') : Buffer.alloc(0); + + const ssidLength = ssidBuffer.length; + const passwordLength = passwordBuffer.length; + const authLength = authBuffer.length; + + + // console.log(`ssid : ${ssidBuffer}, password : ${passwordBuffer}, authtoken : ${authBuffer}`); + + + let buffer = new Buffer([ + 255, + 85, + 0, //Dummy 값 + command, + sensorType, + ssidLength, + passwordLength, + authLength, + ]); + + buffer = Buffer.concat([buffer, ssidBuffer, passwordBuffer, authBuffer, dummy]); + return buffer; + } + + + + init(handler, config) { + this.handler = handler; + this.config = config; + } + + lostController() {} + + setSerialPort(sp) { + this.sp = sp; + } + + + processParsedData(port, sensorType, value) { + // 추출된 데이터에 따른 처리 로직 + let angle; + let portName; + switch (sensorType) { + case this.sensorTypes.DIGITAL_READ: + // console.log(`SEND TO ENTRY FOR DIGITAL_READ : ${port}`); + this.sensorDatas[port] = value; + break; + case this.sensorTypes.ANALOG_READ: + // console.log('SEND TO ENTRY FOR ANALOG_READ'); + portName = `A${port}`; + this.sensorDatas[portName] = value; + break; + case this.sensorTypes.READ_GYRO_ANGLE_SENSOR: + // console.log('SEND TO ENTRY FOR READ_GYRO_ANGLE_SENSOR'); + angle = value - 360 ; + // console.log(angle); + this.sensorDatas[port] = angle; + break; + case this.sensorTypes.READ_GYRO_SENSOR: + // console.log('SEND TO ENTRY FOR READ_GYRO_SENSOR'); + this.sensorDatas[port] = value; + break; + case this.sensorTypes.READ_COLOR_SENSOR: + // console.log(`SEND TO ENTRY FOR READ_COLOR_SENSOR : ${port}`); + portName = `C${port}`; + this.sensorDatas[portName] = value; + break; + case this.sensorTypes.READ_DHT_SENSOR: + portName = `D${port}`; + // console.log(`SEND TO ENTRY FOR READ_DHT_SENSOR : ${portName}`); + this.sensorDatas[portName] = value; + break; + case this.sensorTypes.CONNECTED_BLYNK: + this.sensorDatas.BC = value; + break; + case this.sensorTypes.BLYNK_WRITE: + portName = `V${port}`; + // console.log(`SEND TO ENTRY FOR BLYNK_WRITE : ${portName}`); + this.sensorDatas[portName] = value; + break; + // 기타 케이스 처리... + } + } + + processBuffer() { + /*** + * 데이터 구조 + * 시작 2바이트 [0xFF, 0x55] + * 시작 + [port || etc(1) , SensorType(1), value(2)] + */ + let lastIdx = 0; + // console.log(`received buffer Length : ${this.recvBuffers.length}`); + + for (let i = 0; i < this.recvBuffers.length - 1; i++) { + if (this.recvBuffers[i] === 0xff && this.recvBuffers[i + 1] === 0x55) { + const dataLength = this.recvBuffers[i + 2]; + + if (i + 2 + dataLength <= this.recvBuffers.length) { + const port = this.recvBuffers[i + 3]; + const sensorType = this.recvBuffers[i + 4]; + // console.log(`recvBuffer [${i}]:`, this.recvBuffers.slice(i, i + dataLength).join(' ')); + if (sensorType === this.sensorTypes.READ_GYRO_SENSOR) { + const left = this.recvBuffers[i + 5]; + const right = this.recvBuffers[i + 6]; + const front = this.recvBuffers[i + 7]; + const back = this.recvBuffers[i + 8]; + const up = this.recvBuffers[i + 9]; + const down = this.recvBuffers[i + 10]; + this.sensorDatas[this.gyro_sensor.LEFT] = left; + this.sensorDatas[this.gyro_sensor.RIGHT] = right; + this.sensorDatas[this.gyro_sensor.FRONT] = front; + this.sensorDatas[this.gyro_sensor.BACK] = back; + this.sensorDatas[this.gyro_sensor.UP] = up; + this.sensorDatas[this.gyro_sensor.DOWN] = down; + // console.log(`left : ${left} ,right : ${right} ,front : ${front} ,back : ${back} ,up : ${up} ,down : ${down}`); + } else { + const valueLowByte = this.recvBuffers[i + 5]; + const valueHighByte = this.recvBuffers[i + 6]; + const value = (valueHighByte << 8) | valueLowByte; + // 추출된 데이터 처리 + this.processParsedData(port, sensorType, value); + } + lastIdx = i + dataLength; // 데이터 길이 + } + } + } + // 처리된 데이터 제거 + this.recvBuffers.splice(0, lastIdx); + } + + /** + * 하드웨어에서 온 데이터 처리 + * @param {*} data + */ + handleLocalData(data) { + // console.log(data); + this.recvBuffers.push(...data); // 수신된 데이터를 버퍼에 추가 + this.processBuffer(); + } + + + // 엔트리로 전달할 데이터 + // Web Socket(엔트리)에 전달할 데이터 + requestRemoteData(handler) { + //일정 시간마다 계속 데이터를 보내는 중 + Object.keys(this.sensorDatas).forEach((key) => { + handler.write(key, this.sensorDatas[key]); + // console.log(`key : ${key} , sensorData : ${this.sensorDatas[key]}`); + }); + } + + + // 엔트리에서 받은 데이터에 대한 처리 + // Web Socket 데이터 처리 + handleRemoteData(handler) { + const readData = handler.read('SET'); + if (readData) { + //Write + if (readData.type === this.command.WRITE) { + let buffer = new Buffer([]); + let port; + let value; + let duration; + let printMessage; + let colorValue; + let slideSpeed; + let neoIndex; + let neoNum; + let textSize; + let ssid; + let password; + let authToken; + switch (readData.data.command) { + case this.sensorTypes.DIGITAL_WRITE: + // 실제 하드웨어로 디지털 쓰기 명령을 전송하는 코드 + port = readData.data.pin; + value = readData.data.value; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.DIGITAL_WRITE, + pin : port, + data : value, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.ANALOG_WRITE: + port = readData.data.pin; + value = readData.data.value; + // console.log('ANALOG_WRITE'); + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.ANALOG_WRITE, + pin : port, + data : value, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.PLAY_TONE: + port = readData.data.pin; + duration = readData.data.duration; + value = readData.data.value; + // console.log('PLAY_TONE'); + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.PLAY_TONE, + pin : port, + duration : duration * 10, + data : value, // 주파수값 , + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.SLIDE_NEOPIXEL: + // console.log('SLIDE_NEOPIXEL'); + printMessage = readData.data.message; + colorValue = readData.data.color; + slideSpeed = readData.data.speed; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.SLIDE_NEOPIXEL, + speed : slideSpeed, + message : printMessage, + color : colorValue, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.UPDATE_NEOPIXEL: + // console.log('UPDATE_NEOPIXEL'); + port = readData.data.pin; + neoNum = readData.data.ledNum; + neoIndex = readData.data.ledIndex; + colorValue = readData.data.color; + // console.log('Individual control of a NeoPixel'); + if (neoIndex < 1) { + neoIndex = 1; + } + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.UPDATE_NEOPIXEL, + pin: port, + duration : neoNum, + data : neoIndex, + color : colorValue, + }), + ]); + + + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.UPDATE_ALL_NEOPIXEL: + // console.log('UPDATE_ALL_NEOPIXEL'); + port = readData.data.pin; + neoNum = readData.data.ledNum; + colorValue = readData.data.color; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.UPDATE_ALL_NEOPIXEL, + pin: port, + duration : neoNum, + color : colorValue, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.DISPLAY_INIT_OLED: + // console.log('DISPLAY_INIT_OLED'); + port = readData.data.address; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.DISPLAY_INIT_OLED, + pin: port, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.DISPLAY_OLED: + // console.log('DISPLAY_OLED'); + port = readData.data.x; + value = readData.data.y; + printMessage = readData.data.message; + textSize = readData.data.fontsize; + + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.DISPLAY_OLED, + pin: port, + data: value, + duration: textSize, + message: printMessage, + color : '#000000', + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.CONNECT_WIFI: + // console.log('CONNECT_WIFI'); + ssid = readData.data.ssid; + password = readData.data.password; + authToken = readData.data.authToken; + buffer = Buffer.concat( + [buffer, + this.makeOutputWifiBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.CONNECT_WIFI, + ssid, + password, + auth: authToken, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.BLYNK_VIRTUAL_WRITE: + // console.log('BLYNK_VIRTUAL_WRITE'); + port = readData.data.virtualPin; + value = readData.data.value; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.BLYNK_VIRTUAL_WRITE, + pin: port, + message: value, + color : '#000000', + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.BLYNK_WRITE: + // console.log('BLYNK_WRITE'); + port = readData.data.virtualPin; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.BLYNK_WRITE, + pin: port, + color : '#000000', + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.CONNECTED_BLYNK: + // console.log('CONNECTED_BLYNK'); + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.WRITE, + sensorType : this.sensorTypes.CONNECTED_BLYNK, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + } + } + + //Read + if (readData.type === this.command.READ) { + let buffer = new Buffer([]); + let port; + let value; + // console.log('this.command.READ'); + switch (readData.data.command) { + case this.sensorTypes.DIGITAL_READ: + port = readData.data.pin; + // console.log(`DIGITAL_READ_PORT : ${port}`); + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.READ, + sensorType : this.sensorTypes.DIGITAL_READ, + pin : port, + }), + ]); + if (buffer.length) { + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.ANALOG_READ: + // console.log('ANALOG_READ'); + port = readData.data.pin; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.READ, + sensorType : this.sensorTypes.ANALOG_READ, + pin : port, + }), + ]); + if (buffer.length) { + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.READ_GYRO_SENSOR: + // console.log('READ_GYRO_SENSOR'); + port = readData.data.pin; + // console.log(port); + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.READ, + sensorType : this.sensorTypes.READ_GYRO_SENSOR, + pin : port, + }), + ]); + if (buffer.length) { + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.READ_GYRO_ANGLE_SENSOR: + port = readData.data.pin; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.READ, + sensorType : this.sensorTypes.READ_GYRO_ANGLE_SENSOR, + pin : port, + }), + ]); + if (buffer.length) { + this.sendBuffers.push(buffer); + } + break; + case this.sensorTypes.READ_DHT_SENSOR: + // console.log('readDHTSENSOR'); + port = readData.data.pin; + buffer = Buffer.concat( + [buffer, + this.makeOutputBuffer({ + command : this.command.READ, + pin : port, + sensorType : this.sensorTypes.READ_DHT_SENSOR, + }), + ]); + if (buffer.length) { + //이곳에서 데이터를 SendBuffer에 저장하기 + this.sendBuffers.push(buffer); + } + break; + } + } + } + } + + // 하드웨어에 전달할 데이터 + requestLocalData() { + // 디바이스로 데이터를 보내는 로직. control: slave 인 경우 duration 주기에 맞춰 디바이스에 데이터를 보낸다. + // return 값으로 버퍼를 반환하면 디바이스로 데이터를 보내나, 아두이노의 경우 레거시 코드를 따르고 있다. + if (this.sendBuffers.length > 0) { + this.sp.write(this.sendBuffers.shift(), () => { + if (this.sp) { + this.sp.drain(() => { + this.isDraing = false; + }); + } + }); + } + + return null; + } + + connect() {} + + disconnect(connect) { + if (this.isConnect) { + // clearInterval(this.sensing); + // this.counter = 0; + // this.commandResponseSize = 11; + // this.isSendInitData = false; + // this.isSensorCheck = false; + // this.isConnect = false; + // this.CURRENT_STATUS_COLOR = { + // COLOR: this.STATUS_COLOR_MAP.GREEN, + // APPLIED: false, + // }; + } + } + + reset() {} +} + +module.exports = new hexaboard(); diff --git a/app/modules/hexaboard.json b/app/modules/hexaboard.json new file mode 100644 index 000000000..e9ddde15e --- /dev/null +++ b/app/modules/hexaboard.json @@ -0,0 +1,25 @@ +{ + "id": "5A0101", + "name": { + "en": "HEXABOARD", + "ko": "헥사보드" + }, + "category": "board", + "platform": ["win32", "darwin"], + "icon" : "hexaboard.png", + "module": "hexaboard.js", + "email": "kgu0724@makeitnow.kr", + "url": "https://makeitnow.kr/entry", + "selectPort" : true, + "firmware": "https://makeitnow.tistory.com/236", + "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" + }, + "hardware": { + "type": "serial", + "control": "slave", + "duration": 32, + "baudRate": 115200 + } +} diff --git a/app/modules/hexaboard.png b/app/modules/hexaboard.png new file mode 100644 index 000000000..3729868df Binary files /dev/null and b/app/modules/hexaboard.png differ diff --git a/app/modules/runcoding.json b/app/modules/runcoding.json index b2f7c4982..829c9e0a3 100644 --- a/app/modules/runcoding.json +++ b/app/modules/runcoding.json @@ -10,13 +10,13 @@ "module": "runcoding.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", - "darwin-x64": "CH34x_Install_MAC_10_9_AND_ABOVE/CH34x_Install_V1.3.pkg" + "win32-x64": "CH34x_Install_Windows_v3_4/CH34x_Install_Windows_v3_4.EXE" }, "url": "https://runcoding.co.kr", "email": "runcoding@naver.com", "reconnect": true, "firmware": "runcoding", + "selectPort": true, "hardware": { "type": "serial", "control": "slave", diff --git a/app/modules/suno.json b/app/modules/suno.json index a0e987bc5..4474f0a82 100644 --- a/app/modules/suno.json +++ b/app/modules/suno.json @@ -39,10 +39,7 @@ "type": "serial", "control": "slave", "duration": 48, - "vendor": { - "win32": ["wch.cn", "Arduino"] - }, + "vendor": ["wch.cn", "Arduino"], "baudRate": 57600 - } } diff --git a/build/entry-hw.nsi b/build/entry-hw.nsi index 19bc7df15..d8c8ed741 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.48" +!define PRODUCT_VERSION "1.9.49" !define PRODUCT_PUBLISHER "EntryLabs" !define PRODUCT_WEB_SITE "https://www.playentry.org/" diff --git a/package.json b/package.json index a60ccc3d2..94f435e09 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "entry-hw", - "version": "1.9.48", + "version": "1.9.49", "description": "엔트리 하드웨어 연결 프로그램", "author": "EntryLabs", "main": "./app/src/index.bundle.js",