Merge remote-tracking branch 'upstream/master'
This commit is contained in:
+2
-1
@@ -1,2 +1,3 @@
|
||||
stino.settings
|
||||
*~
|
||||
*bak
|
||||
*bak
|
||||
|
||||
@@ -56,9 +56,9 @@ static uint8_t sendAndWait(uint8_t reqType, uint8_t resType) {
|
||||
msg.type = reqType;
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
sendWrite(msg);
|
||||
for (uint16_t j = 0; j < 20; j++) {
|
||||
for (uint8_t j = 0; j < 20; j++) {
|
||||
wdt_reset();
|
||||
for (uint16_t j = 0; j < 100; j++) {
|
||||
for (uint8_t j = 0; j < 100; j++) {
|
||||
wdt_reset();
|
||||
uint8_t pipe;
|
||||
boolean avail = available(&pipe);
|
||||
@@ -152,6 +152,12 @@ int main () {
|
||||
address(nc.nodeId);
|
||||
}
|
||||
|
||||
// Inform gateway that bootloader does not accept signed messages
|
||||
msg.type = I_REQUEST_SIGNING;
|
||||
mSetLength(msg, 1);
|
||||
msg.data[0] = 0;
|
||||
sendWrite(msg);
|
||||
|
||||
// Read settings from EEPROM
|
||||
eeprom_read_block((void*)&fc, (void*)EEPROM_FIRMWARE_TYPE_ADDRESS, sizeof(struct FirmwareConfig));
|
||||
|
||||
|
||||
+200
-204
@@ -1,4 +1,4 @@
|
||||
:1070000011E0A0E0B1E0E0E4FDE702C005900D92E0
|
||||
:1070000011E0A0E0B1E0E8EFFCE702C005900D92CE
|
||||
:10701000A030B107D9F711E0A0E0B1E001C01D92A6
|
||||
:10702000A83DB107E1F711248091610090E08F70D5
|
||||
:107030009070909301018093000182E090E020E83D
|
||||
@@ -7,208 +7,204 @@
|
||||
:107060000FBE20936000A8951092CF011092D0011E
|
||||
:107070001092D1011092D2011092D3011092D4013A
|
||||
:107080001092D5011092D60184B18E6284B92498F1
|
||||
:1070900085B1857D85B92A9A8AE090E0B3D184E0F4
|
||||
:1070A0006FE520D281E06BE31DD285E06CE41AD25B
|
||||
:1070B00086E0E5D1682F607D676286E013D280E0CC
|
||||
:1070C000DED1682F6C6080E00DD287E060E70AD2E5
|
||||
:1070D0002A9881E090E096D180E5A6D183E7A4D1FB
|
||||
:1070E0002A9A81E090E08ED18DE1C9D1682F666047
|
||||
:1070F0008DE1F8D18CE1C3D1682F6F638CE1F2D1BF
|
||||
:1071000082EEADD181EEABD104D280E0B8D1682F50
|
||||
:107110006E7F80E0E7D182E00FEF1CEF21EE38EACE
|
||||
:1071200048EA50E060E070E002D2A89582E091E089
|
||||
:1071300060E070E043E050E02DEE39E38AD5A89599
|
||||
:107140008091020180930E0180930D014FD22FEFA9
|
||||
:10715000209313018091110192E0909310012093EC
|
||||
:107160000401887083608093110120930F0187E0F0
|
||||
:1071700068E04AD3882309F42AD310920F01809142
|
||||
:1071800002018F3F09F038C081E00FEF1CEF21EEC4
|
||||
:1071900038EA48EA50E060E070E0C9D183E064E09A
|
||||
:1071A00033D3882309F407D38091320182958695E1
|
||||
:1071B0008770813019F48091350105C0882329F446
|
||||
:1071C00085E391E028D580930201809102018F3FF1
|
||||
:1071D00009F4F1D280910201F999FECF1FBA12BCD5
|
||||
:1071E00011BC80BD0FB6F894FA9AF99A0FBE80933D
|
||||
:1071F0000E0180930D01FAD185E091E06BE171E021
|
||||
:1072000048E050E02DEE39E324D5909111019871BA
|
||||
:10721000809110018770806280931001946C90932C
|
||||
:1072200011018091050190910601909315018093C1
|
||||
:1072300014018091070190910801909317018093A8
|
||||
:10724000160180E061E0E0D2882309F4C0D22091E9
|
||||
:10725000370130913801809107019091080128177A
|
||||
:107260003907C9F42091390130913A01809109011F
|
||||
:1072700090910A012817390771F420913B01309150
|
||||
:107280003C0180910B0190910C012817390719F4EA
|
||||
:107290005DD281119CD240913501509136015093BD
|
||||
:1072A0000601409305012091370130913801309358
|
||||
:1072B0000801209307018091390190913A01909340
|
||||
:1072C0000A018093090180913B0190913C019093C8
|
||||
:1072D0000C0180930B01F4E1EF2EF1E0FF2E809181
|
||||
:1072E00010018770806380931001509315014093C3
|
||||
:1072F00014013093170120931601C0E0D0E000E99B
|
||||
:107300001FEFBB24B394E5E0CE2E71E1D72E4DC024
|
||||
:10731000F701D583C48382E063E076D2882309F441
|
||||
:107320004AD2902F90599F77E92FF0E0E15BFE4F12
|
||||
:10733000ABE3B1E080E10D9001928150E1F790372D
|
||||
:1073400009F030C03FB7F894F999FECF83E0F80117
|
||||
:1073500080935700E89507B600FCFDCFA801AFE485
|
||||
:10736000B1E02C9111968C91119790E0982F88277D
|
||||
:10737000820F911D1296FA010C01B0925700E89508
|
||||
:1073800011244E5F5F4FF1E0AF3CBF0751F7F801AA
|
||||
:10739000C0925700E89507B600FCFDCFD092570089
|
||||
:1073A000E8953FBF2196005F1F4F809109019091A2
|
||||
:1073B0000A01C817D90708F4ABCFA895C7D188230D
|
||||
:1073C00049F08BE191E065E071E048E050E024EFA6
|
||||
:1073D00039E35BD4F0D180E090E0F999FECF92BD23
|
||||
:1073E00081BDF89A80B50895F999FECF1FBA92BD74
|
||||
:1073F00081BD60BD0FB6F894FA9AF99A0FBE089550
|
||||
:107400000000089540E050E00BC020E030E00000B4
|
||||
:107410002F5F3F4F61E0243F3607C9F74F5F5F4F53
|
||||
:107420004817590790F308950F931F93182F00E002
|
||||
:10743000E7DF17FD02C02B9801C02B9AE1DF2D9AE0
|
||||
:1074400083B1110F82958170182BDADF2D98D8DF68
|
||||
:107450000F5F083069F7812F1F910F9108951F93D7
|
||||
:10746000182F2A9881E090E0CDDF812FDDDF182FE3
|
||||
:107470002A9A81E090E0C6DF812F1F9108951F9323
|
||||
:10748000182F2A9881E090E0BDDF812F8F71CCDF2B
|
||||
:107490008FEFCADF182F2A9A81E090E0B3DF812FA7
|
||||
:1074A0001F9108950F931F93CF93DF93182FEB0134
|
||||
:1074B000042F2A9881E090E0A5DF1F71812F806260
|
||||
:1074C000B3DF182F03C08991AFDF01500023D9F734
|
||||
:1074D0002A9A81E090E096DF812FDF91CF911F9172
|
||||
:1074E0000F9108950F931F93182F062F2A9881E06C
|
||||
:1074F00090E088DF1F71812F806296DF182F802F28
|
||||
:1075000093DF2A9A81E090E07DDF812F1F910F9118
|
||||
:10751000089580E0B4DF81FD09C080E0B0DF682F0E
|
||||
:10752000626080E0DFDF85E090E06CDF08957F92AD
|
||||
:107530008F929F92AF92BF92CF92DF92EF92FF9283
|
||||
:107540000F931F93DF93CF93CDB7DEB728970FB676
|
||||
:10755000F894DEBF0FBECDBF782E480159016A01F5
|
||||
:107560007B01882381F40093CF019092D001209376
|
||||
:10757000D101B092D2014093D301D092D401609353
|
||||
:10758000D501F092D60189829A82AB82BC82CD82EB
|
||||
:10759000DE82EF82F88681E0871538F0872D865FDE
|
||||
:1075A000BE016F5F7F4F45E07DDF82E068DF21E055
|
||||
:1075B00030E002C0220F331F7A94E2F7682F622B6B
|
||||
:1075C00082E090DF28960FB6F894DEBF0FBECDBFE5
|
||||
:1075D000CF91DF911F910F91FF90EF90DF90CF90AF
|
||||
:1075E000BF90AF909F908F907F9008957F928F92E1
|
||||
:1075F0009F92AF92BF92CF92DF92EF92FF920F9342
|
||||
:107600001F93DF93CF93CDB7DEB728970FB6F894CB
|
||||
:10761000DEBF0FBECDBF8F3F09F483C0082F10E03F
|
||||
:1076200020E030E040E050E060E070E089831A83C1
|
||||
:107630002B833C834D835E836F83788788243CEF64
|
||||
:10764000932E21EEA22E98EAB92E88EAC82EDD24C8
|
||||
:10765000EE24FF24080D81E09981091708F080E0ED
|
||||
:10766000192D91E0AA819A1608F090E0E82FE10F19
|
||||
:1076700081E0E11708F080E0982B1E2F2A2D772457
|
||||
:107680007394BB81AB1608F07724920F81E09217B8
|
||||
:1076900008F080E0782A292F3B2D91E0EC81BE167E
|
||||
:1076A00008F090E0E72DE30F81E0E31708F080E0B9
|
||||
:1076B000982B3E2F4C2D77247394FD81CF1608F024
|
||||
:1076C0007724940F81E0941708F080E0782A492FFE
|
||||
:1076D0005D2D91E08E81D81608F090E0E72DE50F42
|
||||
:1076E00081E0E51708F080E0982B5E2F6E2D77245F
|
||||
:1076F0007394AF81EA1608F07724960F81E096170D
|
||||
:1077000008F080E0782A692F7F0C772D59016A01F3
|
||||
:10771000E92E80E00CDF81E09501A6016E2D772D2A
|
||||
:1077200006DF28960FB6F894DEBF0FBECDBFCF910F
|
||||
:10773000DF911F910F91FF90EF90DF90CF90BF905E
|
||||
:10774000AF909F908F907F90089518954091090178
|
||||
:1077500050910A0164E0440F551F6A95E1F7E0E09B
|
||||
:10776000F0E02FEF3FEF19C084912827822F8295F8
|
||||
:107770008227082E869586958025082E8695802559
|
||||
:107780008770022E232F869507948795302D282702
|
||||
:1077900006948795302528273196E417F50720F3BE
|
||||
:1077A00040E080910B0190910C012817390709F4F2
|
||||
:1077B00041E0842F089528E088E190E00FB6F89426
|
||||
:1077C000A895809360000FBE20936000FFCFBEDFBE
|
||||
:1077D0008823C1F088E10FB6F8948093600010927E
|
||||
:1077E00060000FBE809100019091010120E80FB66A
|
||||
:1077F000F89420936100809361000FBEE0E0F0E018
|
||||
:1078000009950895D8DF08952F923F924F925F9285
|
||||
:107810006F927F928F929F92AF92BF92CF92DF92A0
|
||||
:10782000EF92FF920F931F93DF93CF93CDB7DEB705
|
||||
:10783000E3970FB6F894DEBF0FBECDBF6BA7809362
|
||||
:1078400012016624B9E02B2E312C2C0E3D1E2E0188
|
||||
:107850000894411C511CD101EDE0F1E081E201905E
|
||||
:107860000D928150E1F7109103017C842B852AA7AA
|
||||
:1078700050DE299881E090E0C5DD81EEF0DD82EEFA
|
||||
:10788000EEDD80E0FCDD682F6E7F80E02BDE30E0F7
|
||||
:1078900040E050E060E070E080E090E01CA73DA791
|
||||
:1078A0004EA75FA768AB79AB8AAB9BAB8824ACEFE4
|
||||
:1078B0009A2EF1EEAF2EE8EABE2E78EAC72EDD242E
|
||||
:1078C000EE24FF24012F080D81E0011708F080E06D
|
||||
:1078D000192D91E0EDA59E1608F090E0E82FE10F3C
|
||||
:1078E00081E0E11708F080E0982B1E2F2A2DE1E0BF
|
||||
:1078F000FEA5AF1608F0E0E0920F81E0921708F0C5
|
||||
:1079000080E0E82B292F3B2D91E08FA5B81608F0D9
|
||||
:1079100090E0E30F81E0E31708F080E0982B3E2F22
|
||||
:107920004C2DE1E0F8A9CF1608F0E0E0940F81E0DB
|
||||
:10793000941708F080E0E82B492F5D2D91E089A98C
|
||||
:10794000D81608F090E0E50F81E0E51708F080E038
|
||||
:10795000982B5E2F6E2D81E0EAA9EE1608F080E0EC
|
||||
:10796000E92FE60F91E0E61708F090E0892B8F0DE4
|
||||
:1079700009831A832B833C834D835E83EF8388873F
|
||||
:107980008AE0B20145E08EDD80E1B20145E08ADDAA
|
||||
:10799000FAA5FF3F11F010EA01C010EB769476943F
|
||||
:1079A000769427E0720E2A9881E090E02BDD812FFB
|
||||
:1079B0003BDD81017101E70CF11C04C0F8018191EC
|
||||
:1079C0008F0132DD0E151F05C9F72A9A81E090E07C
|
||||
:1079D00019DD299A81E090E015DD299881E090E099
|
||||
:1079E00011DD8FEF3CDD8073E1F387E060E77ADD46
|
||||
:1079F00084FF02C081EE33DD8CDD80E040DD682F46
|
||||
:107A0000616080E06FDD87E060E76CDD0091CF01B1
|
||||
:107A10001091D0012091D1013091D2014091D30138
|
||||
:107A20005091D4016091D5017091D601802F812BA6
|
||||
:107A3000822B832B842B852B862B872B61F009834C
|
||||
:107A40001A832B833C834D835E836F8378878AE020
|
||||
:107A5000B20145E027DD82EE02DD81EE00DD299AEC
|
||||
:107A600081E090E0CFDCAA24BB24A895CC24DD24BF
|
||||
:107A7000A89587E104DD80FD9CC08FEFF0DCE82E47
|
||||
:107A8000E694F7E0EF22EF1609F493C02A9881E01C
|
||||
:107A900090E0B8DC80E6C8DC8FEFC6DCF82E2A9ACE
|
||||
:107AA00081E090E0AFDC20E22F1518F482EED7DC05
|
||||
:107AB000FF242A9881E090E0A5DC81E6B5DC0EE2A7
|
||||
:107AC00011E006C08FEFB0DCF80181938F01FA94CA
|
||||
:107AD000FF20C1F72A9A81E090E094DC87E060E71C
|
||||
:107AE00001DD2A9881E090E08DDC8E2D886A9CDC97
|
||||
:107AF0008E2D9ADC2A9A81E090E084DC809131011D
|
||||
:107B00008770823009F058C0909130018091020155
|
||||
:107B1000981709F04EC080913201682F70E0CB01B8
|
||||
:107B200087709070039709F034C0809133018830DA
|
||||
:107B300009F02FC040913501242F332727FD3095C0
|
||||
:107B40008091040190E001972817390714F5242F3C
|
||||
:107B50002F5F2093040140912F0140930301F99975
|
||||
:107B6000FECF1FBA81E090E092BD81BD40BD0FB64F
|
||||
:107B7000F894FA9AF99A0FBEF999FECF1FBA42E02B
|
||||
:107B800050E052BD41BD20BD0FB6F894FA9AF99A63
|
||||
:107B90000FBE8091110190E0862797278770907023
|
||||
:107BA000892B39F4809133015BA5851711F481E0AD
|
||||
:107BB00019C081E090E026DC0894C11CD11C64E669
|
||||
:107BC000C616D10409F054CF0894A11CB11C74E16D
|
||||
:107BD000A716B10409F049CF63948AE0681609F04A
|
||||
:107BE0003ACE80E0E3960FB6F894DEBF0FBECDBF6D
|
||||
:107BF000CF91DF911F910F91FF90EF90DF90CF9089
|
||||
:107C0000BF90AF909F908F907F906F905F904F90BC
|
||||
:107C10003F902F900895FC0188279927E89421919F
|
||||
:107C20002032E9F3293010F02E30C8F32B3241F026
|
||||
:107C30002D3239F4689404C00E94613E820F911D78
|
||||
:107C4000219120532A30C0F31EF4909581959F4FC7
|
||||
:107C50000895A0E0B0E0EFE2FEE30C94733E7C01F7
|
||||
:107C6000EB018A01690109C0CE012196F60109954F
|
||||
:107C7000F70181937F010150104001151105A1F713
|
||||
:107C8000CDB7DEB7E8E00C948F3EA0E0B0E0EBE4C7
|
||||
:107C9000FEE30C94733EEC017B018A01690109C08B
|
||||
:107CA000CE012196F70161917F01F60109950150FE
|
||||
:107CB000104001151105A1F7CDB7DEB7E8E00C942F
|
||||
:107CC0008F3E7AE0979F902D879F802D910D1124F4
|
||||
:107CD00008952F923F924F925F926F927F928F9270
|
||||
:107CE0009F92AF92BF92CF92DF92EF92FF920F934B
|
||||
:107CF0001F93CF93DF93CDB7DEB7CA1BDB0B0FB655
|
||||
:107D0000F894DEBF0FBECDBF09942A883988488811
|
||||
:107D10005F846E847D848C849B84AA84B984C884A7
|
||||
:107D2000DF80EE80FD800C811B81AA81B981CE0F9E
|
||||
:107D3000D11D0FB6F894DEBF0FBECDBFED01089583
|
||||
:1070900085B1857D85B92A9A8AE0B1D184E06FE512
|
||||
:1070A00015D281E06BE312D285E06CE40FD286E06A
|
||||
:1070B000DED1682F607D676286E008D280E0D7D19C
|
||||
:1070C000682F6C6080E002D287E060E7FFD12A98E9
|
||||
:1070D00081E095D180E5A2D183E7A0D12A9A81E011
|
||||
:1070E0008ED18DE1C4D1682F66608DE1EFD18CE146
|
||||
:1070F000BED1682F6F638CE1E9D182EEAAD181EE17
|
||||
:10710000A8D1F9D180E0B3D1682F6E7F80E0DED1C5
|
||||
:1071100082E00FEF1CEF21EE38EA48EA50E060E031
|
||||
:1071200070E0F6D1A89582E091E060E070E043E085
|
||||
:1071300050E02AEE39E369D5A89580910201809349
|
||||
:107140000E0180930D0143D22FEF20931301809104
|
||||
:10715000110192E0909310012093040188708360E4
|
||||
:107160008093110120930F0187E068E03ED38823CC
|
||||
:1071700009F41ED310920F01809102018F3F09F094
|
||||
:1071800038C081E00FEF1CEF21EE38EA48EA50E00A
|
||||
:1071900060E070E0BDD183E064E027D3882309F488
|
||||
:1071A000FBD280913201829586958770813019F4E7
|
||||
:1071B0008091350105C0882329F485E391E007D546
|
||||
:1071C00080930201809102018F3F09F4E5D2809102
|
||||
:1071D0000201F999FECF1FBA12BC11BC80BD0FB6D7
|
||||
:1071E000F894FA9AF99A0FBE80930E0180930D01DC
|
||||
:1071F000EED185E091E06BE171E048E050E02AEEED
|
||||
:1072000039E303D590911101987180911001877035
|
||||
:10721000806280931001946C90931101809105011C
|
||||
:1072200090910601909315018093140180910701BC
|
||||
:1072300090910801909317018093160180E061E01E
|
||||
:10724000D4D2882309F4B4D2209137013091380187
|
||||
:10725000809107019091080128173907C9F42091FE
|
||||
:10726000390130913A018091090190910A01281762
|
||||
:10727000390771F420913B0130913C0180910B0161
|
||||
:1072800090910C012817390719F451D2811190D22D
|
||||
:10729000409135015091360150930601409305010C
|
||||
:1072A0002091370130913801309308012093070174
|
||||
:1072B0008091390190913A0190930A0180930901DC
|
||||
:1072C00080913B0190913C0190930C0180930B01C4
|
||||
:1072D000F4E1EF2EF1E0FF2E8091100187708063C2
|
||||
:1072E00080931001509315014093140130931701BE
|
||||
:1072F00020931601C0E0D0E000E91FEFBB24B39457
|
||||
:10730000E5E0CE2E71E1D72E4DC0F701D583C483C1
|
||||
:1073100082E063E06AD2882309F43ED2902F90592C
|
||||
:107320009F77E92FF0E0E15BFE4FABE3B1E080E156
|
||||
:107330000D9001928150E1F7903709F030C03FB7CE
|
||||
:10734000F894F999FECF83E0F80180935700E8950F
|
||||
:1073500007B600FCFDCFA801AFE4B1E02C91119677
|
||||
:107360008C91119790E0982F8827820F911D12968B
|
||||
:10737000FA010C01B0925700E89511244E5F5F4F5F
|
||||
:10738000F1E0AF3CBF0751F7F801C0925700E89514
|
||||
:1073900007B600FCFDCFD0925700E8953FBF21967D
|
||||
:1073A000005F1F4F8091090190910A01C817D9070A
|
||||
:1073B00008F4ABCFA895BBD1882349F08BE191E0CD
|
||||
:1073C00065E071E048E050E021EF39E33AD4E4D1E0
|
||||
:1073D00080E090E0F999FECF92BD81BDF89A80B52A
|
||||
:1073E0000895F999FECF1FBA92BD81BD60BD0FB659
|
||||
:1073F000F894FA9AF99A0FBE08950000089590E063
|
||||
:107400000AC020E030E000002F5F3F4F41E0243F02
|
||||
:107410003407C9F79F5F9817A0F308950F931F9340
|
||||
:10742000182F00E0EADF17FD02C02B9801C02B9A4D
|
||||
:10743000E4DF2D9A83B1110F82958170182BDDDF67
|
||||
:107440002D98DBDF0F5F083069F7812F1F910F91B7
|
||||
:1074500008951F93182F2A9881E0D1DF812FDEDF56
|
||||
:10746000182F2A9A81E0CBDF812F1F9108951F9357
|
||||
:10747000182F2A9881E0C3DF812F8F71CFDF8FEF24
|
||||
:10748000CDDF182F2A9A81E0BADF812F1F9108954E
|
||||
:107490000F931F93CF93DF93182FEB01042F2A989C
|
||||
:1074A00081E0ADDF1F71812F8062B8DF182F03C02C
|
||||
:1074B0008991B4DF01500023D9F72A9A81E09FDF38
|
||||
:1074C000812FDF91CF911F910F9108950F931F93FB
|
||||
:1074D000182F062F2A9881E092DF1F71812F80627A
|
||||
:1074E0009DDF182F802F9ADF2A9A81E088DF812F75
|
||||
:1074F0001F910F91089580E0BADF81FD08C080E000
|
||||
:10750000B6DF682F626080E0E1DF85E078DF089514
|
||||
:107510007F928F929F92AF92BF92CF92DF92EF9223
|
||||
:10752000FF920F931F93DF93CF93CDB7DEB72897CA
|
||||
:107530000FB6F894DEBF0FBECDBF782E48015901BB
|
||||
:107540006A017B01882381F40093CF019092D001DE
|
||||
:107550002093D101B092D2014093D301D092D401B3
|
||||
:107560006093D501F092D60189829A82AB82BC8267
|
||||
:10757000CD82DE82EF82F88681E0871538F0872D94
|
||||
:10758000865FBE016F5F7F4F45E082DF82E06FDF85
|
||||
:1075900021E030E002C0220F331F7A94E2F7682F17
|
||||
:1075A000622B82E093DF28960FB6F894DEBF0FBE01
|
||||
:1075B000CDBFCF91DF911F910F91FF90EF90DF90A2
|
||||
:1075C000CF90BF90AF909F908F907F9008957F92C3
|
||||
:1075D0008F929F92AF92BF92CF92DF92EF92FF92E3
|
||||
:1075E0000F931F93DF93CF93CDB7DEB728970FB6D6
|
||||
:1075F000F894DEBF0FBECDBF8F3F09F483C0082FC4
|
||||
:1076000010E020E030E040E050E060E070E089838E
|
||||
:107610001A832B833C834D835E836F837887882412
|
||||
:107620003CEF932E21EEA22E98EAB92E88EAC82EBE
|
||||
:10763000DD24EE24FF24080D81E09981091708F06C
|
||||
:1076400080E0192D91E0AA819A1608F090E0E82FC9
|
||||
:10765000E10F81E0E11708F080E0982B1E2F2A2D22
|
||||
:1076600077247394BB81AB1608F07724920F81E0E6
|
||||
:10767000921708F080E0782A292F3B2D91E0EC81C9
|
||||
:10768000BE1608F090E0E72DE30F81E0E31708F065
|
||||
:1076900080E0982B3E2F4C2D77247394FD81CF16DC
|
||||
:1076A00008F07724940F81E0941708F080E0782A9E
|
||||
:1076B000492F5D2D91E08E81D81608F090E0E72DDE
|
||||
:1076C000E50F81E0E51708F080E0982B5E2F6E2D26
|
||||
:1076D00077247394AF81EA1608F07724960F81E03F
|
||||
:1076E000961708F080E0782A692F7F0C772D5901D2
|
||||
:1076F0006A01E92E80E00CDF81E09501A6016E2D84
|
||||
:10770000772D06DF28960FB6F894DEBF0FBECDBFEB
|
||||
:10771000CF91DF911F910F91FF90EF90DF90CF906D
|
||||
:10772000BF90AF909F908F907F9008951895409153
|
||||
:10773000090150910A0164E0440F551F6A95E1F771
|
||||
:10774000E0E0F0E02FEF3FEF19C084912827822F6F
|
||||
:1077500082958227082E869586958025082E869507
|
||||
:1077600080258770022E232F869507948795302DCC
|
||||
:10777000282706948795302528273196E417F507A2
|
||||
:1077800020F340E080910B0190910C0128173907FC
|
||||
:1077900009F441E0842F089528E088E190E00FB6D5
|
||||
:1077A000F894A895809360000FBE20936000FFCFEF
|
||||
:1077B000BEDF8823C1F088E10FB6F89480936000A3
|
||||
:1077C000109260000FBE809100019091010120E8AD
|
||||
:1077D0000FB6F89420936100809361000FBEE0E043
|
||||
:1077E000F0E009950895D8DF08952F923F924F92C7
|
||||
:1077F0005F926F927F928F929F92AF92BF92CF9241
|
||||
:10780000DF92EF92FF920F931F93DF93CF93CDB749
|
||||
:10781000DEB7E3970FB6F894DEBF0FBECDBF6BA700
|
||||
:10782000809312016624B9E02B2E312C2C0E3D1EC4
|
||||
:107830002E010894411C511CD101EDE0F1E081E2E0
|
||||
:1078400001900D928150E1F7109103017C842B850A
|
||||
:107850002AA751DE299881E0D2DD81EEFADD82EEA1
|
||||
:10786000F8DD80E004DE682F6E7F80E02FDE30E000
|
||||
:1078700040E050E060E070E080E090E01CA73DA7B1
|
||||
:107880004EA75FA768AB79AB8AAB9BAB8824ACEF04
|
||||
:107890009A2EF1EEAF2EE8EABE2E78EAC72EDD244E
|
||||
:1078A000EE24FF24012F080D81E0011708F080E08D
|
||||
:1078B000192D91E0EDA59E1608F090E0E82FE10F5C
|
||||
:1078C00081E0E11708F080E0982B1E2F2A2DE1E0DF
|
||||
:1078D000FEA5AF1608F0E0E0920F81E0921708F0E5
|
||||
:1078E00080E0E82B292F3B2D91E08FA5B81608F0FA
|
||||
:1078F00090E0E30F81E0E31708F080E0982B3E2F43
|
||||
:107900004C2DE1E0F8A9CF1608F0E0E0940F81E0FB
|
||||
:10791000941708F080E0E82B492F5D2D91E089A9AC
|
||||
:10792000D81608F090E0E50F81E0E51708F080E058
|
||||
:10793000982B5E2F6E2D81E0EAA9EE1608F080E00C
|
||||
:10794000E92FE60F91E0E61708F090E0892B8F0D04
|
||||
:1079500009831A832B833C834D835E83EF8388875F
|
||||
:107960008AE0B20145E094DD80E1B20145E090DDBE
|
||||
:10797000FAA5FF3F11F010EA01C010EB769476945F
|
||||
:10798000769427E0720E2A9881E039DD812F46DD5A
|
||||
:1079900081017101E70CF11C04C0F80181918F0194
|
||||
:1079A0003DDD0E151F05C9F72A9A81E028DD299AC9
|
||||
:1079B00081E025DD299881E022DD8FEF4ADD8073AB
|
||||
:1079C000E1F387E060E782DD84FF02C081EE41DD04
|
||||
:1079D00092DD80E04CDD682F616080E077DD87E03C
|
||||
:1079E00060E774DD0091CF011091D0012091D101A9
|
||||
:1079F0003091D2014091D3015091D4016091D501D1
|
||||
:107A00007091D601802F812B822B832B842B852B89
|
||||
:107A1000862B872B61F009831A832B833C834D834C
|
||||
:107A20005E836F8378878AE0B20145E031DD82EEC4
|
||||
:107A300010DD81EE0EDD299A81E0E1DCCC24A895F1
|
||||
:107A4000DD24A89587E113DD80FD96C08FEF01DD71
|
||||
:107A5000E82EE694F7E0EF22EF1609F48DC02A989D
|
||||
:107A600081E0CDDC80E6DADC8FEFD8DCF82E2A9AD4
|
||||
:107A700081E0C5DC20E22F1518F482EEEADCFF2459
|
||||
:107A80002A9881E0BCDC81E6C9DC0EE211E006C088
|
||||
:107A90008FEFC4DCF80181938F01FA94FF20C1F7C6
|
||||
:107AA0002A9A81E0ACDC87E060E710DD2A9881E06B
|
||||
:107AB000A6DC8E2D886AB2DC8E2DB0DC2A9A81E09D
|
||||
:107AC0009EDC809131018770823009F057C090911F
|
||||
:107AD000300180910201981709F04EC08091320167
|
||||
:107AE000682F70E0CB0187709070039709F034C065
|
||||
:107AF00080913301883009F02FC040913501242F47
|
||||
:107B0000332727FD30958091040190E001972817D5
|
||||
:107B1000390714F5242F2F5F2093040180912F0142
|
||||
:107B200080930301F999FECF1FBA41E050E052BDA6
|
||||
:107B300041BD80BD0FB6F894FA9AF99A0FBEF99933
|
||||
:107B4000FECF1FBA82E090E092BD81BD20BD0FB68E
|
||||
:107B5000F894FA9AF99A0FBE8091110190E0862765
|
||||
:107B6000972787709070892B39F4809133019BA5FA
|
||||
:107B7000891711F481E012C081E041DCD394E4E67E
|
||||
:107B8000DE1609F05ECFC394F4E1CF1609F057CFAB
|
||||
:107B900063942AE0621609F04FCE80E0E3960FB6B8
|
||||
:107BA000F894DEBF0FBECDBFCF91DF911F910F9133
|
||||
:107BB000FF90EF90DF90CF90BF90AF909F908F900D
|
||||
:107BC0007F906F905F904F903F902F900895FC01B1
|
||||
:107BD00088279927E89421912032E9F3293010F081
|
||||
:107BE0002E30C8F32B3241F02D3239F4689404C0A2
|
||||
:107BF0000E943D3E820F911D219120532A30C0F3F7
|
||||
:107C00001EF4909581959F4F0895A0E0B0E0EBE0C1
|
||||
:107C1000FEE30C944F3E7C01EB018A01690109C02F
|
||||
:107C2000CE012196F6010995F70181937F0101505C
|
||||
:107C3000104001151105A1F7CDB7DEB7E8E00C94AF
|
||||
:107C40006B3EA0E0B0E0E7E2FEE30C944F3EEC01B7
|
||||
:107C50007B018A01690109C0CE012196F70161917A
|
||||
:107C60007F01F60109950150104001151105A1F79A
|
||||
:107C7000CDB7DEB7E8E00C946B3E7AE0979F902D8D
|
||||
:107C8000879F802D910D112408952F923F924F923E
|
||||
:107C90005F926F927F928F929F92AF92BF92CF929C
|
||||
:107CA000DF92EF92FF920F931F93CF93DF93CDB7A5
|
||||
:107CB000DEB7CA1BDB0B0FB6F894DEBF0FBECDBF1D
|
||||
:107CC00009942A88398848885F846E847D848C84EE
|
||||
:107CD0009B84AA84B984C884DF80EE80FD800C81F7
|
||||
:107CE0001B81AA81B981CE0FD11D0FB6F894DEBFDA
|
||||
:087CF0000FBECDBFED010895A8
|
||||
:040000030000700089
|
||||
:00000001FF
|
||||
|
||||
@@ -32,8 +32,9 @@ static void delayu() {
|
||||
asm("nop");
|
||||
}
|
||||
|
||||
static void delaym(uint16_t t) {
|
||||
uint16_t d, a;
|
||||
static void delaym(uint8_t t) {
|
||||
uint8_t d;
|
||||
uint16_t a;
|
||||
for (d = 0; d < t; d++)
|
||||
for (a = 0; a < DELAY_M; a++)
|
||||
asm("nop");
|
||||
|
||||
@@ -706,5 +706,8 @@ dbc.connect('mongodb://' + dbAddress + ':' + dbPort + '/' + dbName, function(err
|
||||
} else {
|
||||
throw new Error('unknown Gateway type');
|
||||
}
|
||||
setInterval(function() {
|
||||
sendTime(BROADCAST_ADDRESS, NODE_SENSOR_ID, gw);
|
||||
}, 5*60*1000);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Arduino
|
||||
=======
|
||||
|
||||
MySensors Arduino Library v1.4
|
||||
MySensors Arduino Library v1.5
|
||||
|
||||
Please visit www.mysensors.org for more information
|
||||
|
||||
@@ -16,7 +16,7 @@ MysensorsMicro.bootloader.unlock_bits=0x3F
|
||||
MysensorsMicro.bootloader.lock_bits=0x0F
|
||||
MysensorsMicro.bootloader.low_fuses=0xE2
|
||||
MysensorsMicro.bootloader.high_fuses=0xD2
|
||||
MysensorsMicro.bootloader.extended_fuses=0xFE
|
||||
MysensorsMicro.bootloader.extended_fuses=0x06
|
||||
MysensorsMicro.bootloader.file=DualOptiboot/optiboot_atmega328_pro_8MHz.hex
|
||||
|
||||
MysensorsMicro.build.board=AVR_MICRO8
|
||||
|
||||
@@ -304,7 +304,7 @@ void LCD::createChar(uint8_t location, uint8_t charmap[])
|
||||
}
|
||||
|
||||
#ifdef __AVR__
|
||||
void LCD::createChar(uint8_t location, const unsigned char charmap[])
|
||||
void LCD::createChar(uint8_t location, const unsigned char charmap[])
|
||||
{
|
||||
location &= 0x7; // we only have 8 memory locations 0-7
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ public:
|
||||
(0 to 7)
|
||||
@param charmap[in] the bitmap array representing each row of the character.
|
||||
*/
|
||||
void createChar(uint8_t location, const unsigned char charmap[]);
|
||||
void createChar(uint8_t location, const unsigned char charmap[]);
|
||||
#endif // __AVR__
|
||||
|
||||
/*!
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
Javier Valencia <javiervalencia80@gmail.com>
|
||||
|
||||
History:
|
||||
|
||||
05Apr2015 TRL V0.6a added support for ATmega1284P
|
||||
29/Dec/11 - V0.6 added support for ATmega32u4, AT90USB646, AT90USB1286 (paul@pjrc.com)
|
||||
some improvements added by Bill Perry
|
||||
note: uses timer4 on Atmega32u4
|
||||
@@ -49,7 +51,7 @@ void MsTimer2::set(unsigned long ms, void (*f)()) {
|
||||
|
||||
func = f;
|
||||
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
TIMSK2 &= ~(1<<TOIE2);
|
||||
TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
|
||||
TCCR2B &= ~(1<<WGM22);
|
||||
@@ -147,7 +149,7 @@ void MsTimer2::set(unsigned long ms, void (*f)()) {
|
||||
void MsTimer2::start() {
|
||||
count = 0;
|
||||
overflowing = 0;
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
TCNT2 = tcnt2;
|
||||
TIMSK2 |= (1<<TOIE2);
|
||||
#elif defined (__AVR_ATmega128__)
|
||||
@@ -164,7 +166,7 @@ void MsTimer2::start() {
|
||||
}
|
||||
|
||||
void MsTimer2::stop() {
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
TIMSK2 &= ~(1<<TOIE2);
|
||||
#elif defined (__AVR_ATmega128__)
|
||||
TIMSK &= ~(1<<TOIE2);
|
||||
@@ -192,7 +194,7 @@ ISR(TIMER4_OVF_vect) {
|
||||
#else
|
||||
ISR(TIMER2_OVF_vect) {
|
||||
#endif
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega48__) || defined (__AVR_ATmega88__) || defined (__AVR_ATmega328P__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
TCNT2 = MsTimer2::tcnt2;
|
||||
#elif defined (__AVR_ATmega128__)
|
||||
TCNT2 = MsTimer2::tcnt2;
|
||||
@@ -203,4 +205,3 @@ ISR(TIMER2_OVF_vect) {
|
||||
#endif
|
||||
MsTimer2::_overflow();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
char dummyvar; // to get Arduinoi IDE to include core headers properly
|
||||
|
||||
/*
|
||||
MsTimer2 is a small and very easy to use library to interface Timer2 with
|
||||
humans. It's called MsTimer2 because it "hardcodes" a resolution of 1
|
||||
millisecond on timer2
|
||||
For Details see: http://www.arduino.cc/playground/Main/MsTimer2
|
||||
*/
|
||||
#include <MsTimer2.h>
|
||||
|
||||
// Switch on LED on and off each half second
|
||||
|
||||
#if defined(ARDUINO) && ARDUINO >= 100
|
||||
const int led_pin = LED_BUILTIN; // 1.0 built in LED pin var
|
||||
#else
|
||||
#if defined(CORE_LED0_PIN)
|
||||
const int led_pin = CORE_LED0_PIN; // 3rd party LED pin define
|
||||
#else
|
||||
const int led_pin = 13; // default to pin 13
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
void flash()
|
||||
{
|
||||
static boolean output = HIGH;
|
||||
|
||||
digitalWrite(led_pin, output);
|
||||
output = !output;
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
pinMode(led_pin, OUTPUT);
|
||||
|
||||
MsTimer2::set(500, flash); // 500ms period
|
||||
MsTimer2::start();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
MsTimer2 KEYWORD1
|
||||
set KEYWORD2
|
||||
start KEYWORD2
|
||||
stop KEYWORD2
|
||||
+137
-17
@@ -1,23 +1,143 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MyConfig_h
|
||||
#define MyConfig_h
|
||||
#include <stdint.h>
|
||||
|
||||
/***
|
||||
* Configure Sensor Network
|
||||
*/
|
||||
#define RF24_CHANNEL 76 //RF channel for the sensor net, 0-127
|
||||
#define RF24_DATARATE RF24_250KBPS //RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
|
||||
#define RF24_PA_LEVEL RF24_PA_MAX //Sensor PA Level == RF24_PA_MIN=-18dBm, RF24_PA_LOW=-12dBm, RF24_PA_HIGH=-6dBM, and RF24_PA_MAX=0dBm
|
||||
#define RF24_PA_LEVEL_GW RF24_PA_LOW //Gateway PA Level, defaults to Sensor net PA Level. Tune here if using an amplified nRF2401+ in your gateway.
|
||||
#define BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL) // This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network.
|
||||
|
||||
// MySensors online examples defaults
|
||||
#define DEFAULT_CE_PIN 9
|
||||
#define DEFAULT_CS_PIN 10
|
||||
|
||||
|
||||
/***
|
||||
* Enable/Disable debug logging
|
||||
*/
|
||||
// Enable debug flag for debug prints. This will add a lot to the size of the final sketch but good
|
||||
// to see what is actually is happening when developing
|
||||
#define DEBUG
|
||||
|
||||
// Serial output baud rate (for debug prints and serial gateway)
|
||||
#define BAUD_RATE 115200
|
||||
|
||||
|
||||
/**********************************
|
||||
* Over the air firmware updates
|
||||
***********************************/
|
||||
|
||||
// The following define enables the safe over-the-air firmware update feature
|
||||
// which requires external flash and the DualOptiBoot bootloader.
|
||||
// Note: You can still have OTA FW updates without external flash but it
|
||||
// requires the MYSBootloader and disabled MY_OTA_FIRMWARE_FEATURE
|
||||
//#define MY_OTA_FIRMWARE_FEATURE
|
||||
// Slave select pin for external flash
|
||||
#define MY_OTA_FLASH_SS 8
|
||||
// Flash jdecid
|
||||
#define MY_OTA_FLASH_JDECID 0x1F65
|
||||
|
||||
|
||||
/**********************************
|
||||
* Information LEDs blinking
|
||||
***********************************/
|
||||
// This feature enables LEDs blinking on message receive, transmit
|
||||
// or if some error occured. This was commonly used only in gateways,
|
||||
// but now can be used in any sensor node. Also the LEDs can now be
|
||||
// disabled in the gateway.
|
||||
|
||||
// #define WITH_LEDS_BLINKING
|
||||
|
||||
// default LEDs blinking period in milliseconds
|
||||
#define DEFAULT_LED_BLINK_PERIOD 300
|
||||
// The RX LED default pin
|
||||
#define DEFAULT_RX_LED_PIN 6
|
||||
// The TX LED default pin
|
||||
#define DEFAULT_TX_LED_PIN 5
|
||||
// The Error LED default pin
|
||||
#define DEFAULT_ERR_LED_PIN 4
|
||||
|
||||
|
||||
/**********************************
|
||||
* Message Signing Settings
|
||||
***********************************/
|
||||
// Disable to completly disable signing functionality in library
|
||||
//#define MY_SIGNING_FEATURE
|
||||
|
||||
// Define a suitable timeout for a signature verification session
|
||||
// Consider the turnaround from a nonce being generated to a signed message being received
|
||||
// which might vary, especially in networks with many hops. 5s ought to be enough for anyone.
|
||||
#define MY_VERIFICATION_TIMEOUT_MS 5000
|
||||
|
||||
// Enable to turn on whitelisting
|
||||
// When enabled, a signing node will salt the signature with it's unique signature and nodeId.
|
||||
// The verifying node will look up the sender in a local table of trusted nodes and
|
||||
// do the corresponding salting in order to verify the signature.
|
||||
// For this reason, if whitelisting is enabled on one of the nodes in a sign-verify pair, both
|
||||
// nodes have to implement whitelisting for this to work.
|
||||
// Note that a node can still transmit a non-salted message (i.e. have whitelisting disabled)
|
||||
// to a node that has whitelisting enabled (assuming the receiver does not have a matching entry
|
||||
// for the sender in it's whitelist)
|
||||
//#define MY_SECURE_NODE_WHITELISTING
|
||||
|
||||
// MySigningAtsha204 default setting
|
||||
#define MY_ATSHA204_PIN 17 // A3 - pin where ATSHA204 is attached
|
||||
|
||||
// MySigningAtsha204Soft default settings
|
||||
#define MY_RANDOMSEED_PIN 7 // A7 - Pin used for random generation (do not connect anything to this)
|
||||
|
||||
// Key to use for HMAC calculation in MySigningAtsha204Soft (32 bytes)
|
||||
#define MY_HMAC_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
|
||||
|
||||
/**********************************
|
||||
* NRF24L01 Driver Defaults
|
||||
***********************************/
|
||||
#define RF24_CE_PIN 9
|
||||
#define RF24_CS_PIN 10
|
||||
#define RF24_PA_LEVEL RF24_PA_MAX
|
||||
#define RF24_PA_LEVEL_GW RF24_PA_LOW
|
||||
// RF channel for the sensor net, 0-127
|
||||
#define RF24_CHANNEL 76
|
||||
//RF24_250KBPS for 250kbs, RF24_1MBPS for 1Mbps, or RF24_2MBPS for 2Mbps
|
||||
#define RF24_DATARATE RF24_250KBPS
|
||||
// This is also act as base value for sensor nodeId addresses. Change this (or channel) if you have more than one sensor network.
|
||||
#define RF24_BASE_RADIO_ID ((uint64_t)0xA8A8E1FC00LL)
|
||||
|
||||
// Enable SOFTSPI for NRF24L01 when using the W5100 Ethernet module
|
||||
//#define SOFTSPI
|
||||
#ifdef SOFTSPI
|
||||
// Define the soft SPI pins used for NRF radio
|
||||
const uint8_t SOFT_SPI_MISO_PIN = 16;
|
||||
const uint8_t SOFT_SPI_MOSI_PIN = 15;
|
||||
const uint8_t SOFT_SPI_SCK_PIN = 14;
|
||||
#endif
|
||||
|
||||
|
||||
/**********************************
|
||||
* RFM69 Driver Defaults
|
||||
***********************************/
|
||||
// Default network id. Use the same for all nodes that will talk to each other
|
||||
#define RFM69_NETWORKID 100
|
||||
|
||||
// Default frequency to use. This must match the hardware version of the RFM69 radio (uncomment one):
|
||||
// #define RFM69_FREQUENCY RF69_433MHZ
|
||||
#define RFM69_FREQUENCY RF69_868MHZ
|
||||
//#define FREQUENCY RF69_915MHZ
|
||||
|
||||
// Enable this for encryption of packets
|
||||
//#define RFM69_ENABLE_ENCRYPTION
|
||||
#define RFM69_ENCRYPTKEY "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyGateway.h"
|
||||
#include "utility/MsTimer2.h"
|
||||
#include "utility/PinChangeInt.h"
|
||||
|
||||
|
||||
int8_t pinRx;
|
||||
int8_t pinTx;
|
||||
int8_t pinEr;
|
||||
boolean buttonTriggeredInclusion;
|
||||
volatile uint8_t countRx;
|
||||
volatile uint8_t countTx;
|
||||
volatile uint8_t countErr;
|
||||
boolean inclusionMode; // Keeps track on inclusion mode
|
||||
|
||||
#define LED_ON (LOW)
|
||||
#define LED_OFF (HIGH)
|
||||
|
||||
|
||||
MyGateway::MyGateway(uint8_t _cepin, uint8_t _cspin, uint8_t _inclusion_time, int8_t _inclusion_pin, int8_t _rx, int8_t _tx, int8_t _er) : MySensor(_cepin, _cspin) {
|
||||
pinInclusion = _inclusion_pin;
|
||||
inclusionTime = _inclusion_time;
|
||||
pinRx = _rx;
|
||||
pinTx = _tx;
|
||||
pinEr = _er;
|
||||
}
|
||||
|
||||
|
||||
void MyGateway::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate, void (*inDataCallback)(char *)) {
|
||||
Serial.begin(BAUD_RATE);
|
||||
repeaterMode = true;
|
||||
isGateway = true;
|
||||
autoFindParent = false;
|
||||
setupRepeaterMode();
|
||||
|
||||
if (inDataCallback != NULL) {
|
||||
useWriteCallback = true;
|
||||
dataCallback = inDataCallback;
|
||||
} else {
|
||||
useWriteCallback = false;
|
||||
}
|
||||
|
||||
nc.nodeId = 0;
|
||||
nc.parentNodeId = 0;
|
||||
nc.distance = 0;
|
||||
inclusionMode = 0;
|
||||
buttonTriggeredInclusion = false;
|
||||
countRx = 0;
|
||||
countTx = 0;
|
||||
countErr = 0;
|
||||
|
||||
// Setup led pins & set initial state of leds
|
||||
if (pinRx >= 0)
|
||||
{
|
||||
digitalWrite(pinRx, LED_OFF);
|
||||
pinMode(pinRx, OUTPUT);
|
||||
}
|
||||
if (pinTx >= 0)
|
||||
{
|
||||
digitalWrite(pinTx, LED_OFF);
|
||||
pinMode(pinTx, OUTPUT);
|
||||
}
|
||||
if (pinEr >= 0)
|
||||
{
|
||||
digitalWrite(pinEr, LED_OFF);
|
||||
pinMode(pinEr, OUTPUT);
|
||||
}
|
||||
// Setup digital in that triggers inclusion mode
|
||||
if (pinInclusion >= 0)
|
||||
{
|
||||
pinMode(pinInclusion, INPUT);
|
||||
// Add interrupt for inclusion button to pin
|
||||
PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING);
|
||||
}
|
||||
|
||||
// Start up the radio library
|
||||
setupRadio(paLevel, channel, dataRate);
|
||||
RF24::openReadingPipe(WRITE_PIPE, BASE_RADIO_ID);
|
||||
RF24::openReadingPipe(CURRENT_NODE_PIPE, BASE_RADIO_ID);
|
||||
RF24::startListening();
|
||||
|
||||
// Add led timer interrupt
|
||||
MsTimer2::set(300, ledTimersInterrupt);
|
||||
MsTimer2::start();
|
||||
|
||||
// Send startup log message on serial
|
||||
serial(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
||||
}
|
||||
|
||||
|
||||
void startInclusionInterrupt() {
|
||||
buttonTriggeredInclusion = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MyGateway::checkButtonTriggeredInclusion() {
|
||||
if (buttonTriggeredInclusion) {
|
||||
// Ok, someone pressed the inclusion button on the gateway
|
||||
// start inclusion mode for 1 munute.
|
||||
serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
buttonTriggeredInclusion = false;
|
||||
setInclusionMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MyGateway::checkInclusionFinished() {
|
||||
if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) {
|
||||
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode
|
||||
setInclusionMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t MyGateway::h2i(char c) {
|
||||
uint8_t i = 0;
|
||||
if (c <= '9')
|
||||
i += c - '0';
|
||||
else if (c >= 'a')
|
||||
i += c - 'a' + 10;
|
||||
else
|
||||
i += c - 'A' + 10;
|
||||
return i;
|
||||
}
|
||||
|
||||
void MyGateway::parseAndSend(char *commandBuffer) {
|
||||
boolean ok = false;
|
||||
char *str, *p, *value=NULL;
|
||||
uint8_t bvalue[MAX_PAYLOAD];
|
||||
uint8_t blen = 0;
|
||||
int i = 0;
|
||||
uint16_t destination = 0;
|
||||
uint8_t sensor = 0;
|
||||
uint8_t command = 0;
|
||||
uint8_t type = 0;
|
||||
uint8_t ack = 0;
|
||||
|
||||
// Extract command data coming on serial line
|
||||
for (str = strtok_r(commandBuffer, ";", &p); // split using semicolon
|
||||
str && i < 6; // loop while str is not null an max 5 times
|
||||
str = strtok_r(NULL, ";", &p) // get subsequent tokens
|
||||
) {
|
||||
switch (i) {
|
||||
case 0: // Radioid (destination)
|
||||
destination = atoi(str);
|
||||
break;
|
||||
case 1: // Childid
|
||||
sensor = atoi(str);
|
||||
break;
|
||||
case 2: // Message type
|
||||
command = atoi(str);
|
||||
break;
|
||||
case 3: // Should we request ack from destination?
|
||||
ack = atoi(str);
|
||||
break;
|
||||
case 4: // Data type
|
||||
type = atoi(str);
|
||||
break;
|
||||
case 5: // Variable value
|
||||
if (command == C_STREAM) {
|
||||
blen = 0;
|
||||
uint8_t val;
|
||||
while (*str) {
|
||||
val = h2i(*str++) << 4;
|
||||
val += h2i(*str++);
|
||||
bvalue[blen] = val;
|
||||
blen++;
|
||||
}
|
||||
} else {
|
||||
value = str;
|
||||
// Remove ending carriage return character (if it exists)
|
||||
uint8_t lastCharacter = strlen(value)-1;
|
||||
if (value[lastCharacter] == '\r')
|
||||
value[lastCharacter] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if (destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
||||
// Handle messages directed to gateway
|
||||
if (type == I_VERSION) {
|
||||
// Request for version
|
||||
serial(PSTR("0;0;%d;0;%d;%s\n"),C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
||||
} else if (type == I_INCLUSION_MODE) {
|
||||
// Request to change inclusion mode
|
||||
setInclusionMode(atoi(value) == 1);
|
||||
}
|
||||
} else {
|
||||
txBlink(1);
|
||||
msg.sender = GATEWAY_ADDRESS;
|
||||
msg.destination = destination;
|
||||
msg.sensor = sensor;
|
||||
msg.type = type;
|
||||
mSetCommand(msg,command);
|
||||
mSetRequestAck(msg,ack?1:0);
|
||||
mSetAck(msg,false);
|
||||
if (command == C_STREAM)
|
||||
msg.set(bvalue, blen);
|
||||
else
|
||||
msg.set(value);
|
||||
ok = sendRoute(msg);
|
||||
if (!ok) {
|
||||
errBlink(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MyGateway::setInclusionMode(boolean newMode) {
|
||||
if (newMode != inclusionMode)
|
||||
inclusionMode = newMode;
|
||||
// Send back mode change on serial line to ack command
|
||||
serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0);
|
||||
|
||||
if (inclusionMode) {
|
||||
inclusionStartTime = millis();
|
||||
}
|
||||
}
|
||||
|
||||
void MyGateway::processRadioMessage() {
|
||||
if (process()) {
|
||||
// A new message was received from one of the sensors
|
||||
MyMessage message = getLastMessage();
|
||||
if (mGetCommand(message) == C_PRESENTATION && inclusionMode) {
|
||||
rxBlink(3);
|
||||
} else {
|
||||
rxBlink(1);
|
||||
}
|
||||
// Pass along the message from sensors to serial line
|
||||
serial(message);
|
||||
}
|
||||
|
||||
checkButtonTriggeredInclusion();
|
||||
checkInclusionFinished();
|
||||
}
|
||||
|
||||
void MyGateway::serial(const char *fmt, ... ) {
|
||||
va_list args;
|
||||
va_start (args, fmt );
|
||||
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
||||
va_end (args);
|
||||
Serial.print(serialBuffer);
|
||||
if (useWriteCallback) {
|
||||
// We have a registered write callback (probably Ethernet)
|
||||
dataCallback(serialBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
void MyGateway::serial(MyMessage &msg) {
|
||||
serial(PSTR("%d;%d;%d;%d;%d;%s\n"),msg.sender, msg.sensor, mGetCommand(msg), mGetAck(msg), msg.type, msg.getString(convBuf));
|
||||
}
|
||||
|
||||
|
||||
void ledTimersInterrupt() {
|
||||
if (pinRx >= 0)
|
||||
{
|
||||
if(countRx && countRx != 255) {
|
||||
// switch led on
|
||||
digitalWrite(pinRx, LED_ON);
|
||||
} else if(!countRx) {
|
||||
// switching off
|
||||
digitalWrite(pinRx, LED_OFF);
|
||||
}
|
||||
}
|
||||
if(countRx != 255) { countRx--; }
|
||||
|
||||
if (pinTx >= 0)
|
||||
{
|
||||
if(countTx && countTx != 255) {
|
||||
// switch led on
|
||||
digitalWrite(pinTx, LED_ON);
|
||||
} else if(!countTx) {
|
||||
// switching off
|
||||
digitalWrite(pinTx, LED_OFF);
|
||||
}
|
||||
}
|
||||
if(countTx != 255) { countTx--; }
|
||||
else if(inclusionMode) { countTx = 8; }
|
||||
|
||||
if (pinEr >= 0)
|
||||
{
|
||||
if(countErr && countErr != 255) {
|
||||
// switch led on
|
||||
digitalWrite(pinEr, LED_ON);
|
||||
} else if(!countErr) {
|
||||
// switching off
|
||||
digitalWrite(pinEr, LED_OFF);
|
||||
}
|
||||
}
|
||||
if(countErr != 255) { countErr--; }
|
||||
}
|
||||
|
||||
void MyGateway::rxBlink(uint8_t cnt) {
|
||||
if(countRx == 255) { countRx = cnt; }
|
||||
}
|
||||
void MyGateway::txBlink(uint8_t cnt) {
|
||||
if(countTx == 255 && !inclusionMode) { countTx = cnt; }
|
||||
}
|
||||
void MyGateway::errBlink(uint8_t cnt) {
|
||||
if(countErr == 255) { countErr = cnt; }
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyGateway_h
|
||||
#define MyGateway_h
|
||||
|
||||
#include "MySensor.h"
|
||||
|
||||
#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller
|
||||
#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller
|
||||
|
||||
class MyGateway : public MySensor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Creates a new instance of MyGateway class.
|
||||
* If you don't use status leds and/or inclusion mode button on your arduino gateway
|
||||
* you can disable this functionality by calling the 2 argument constructor.
|
||||
*
|
||||
* @param _cepin The pin attached to RF24 Chip Enable on the RF module (default 9)
|
||||
* @param _cspin The pin attached to RF24 Chip Select (defualt 10)
|
||||
* @param _inclusion_time Time of inclusion mode (in minutes, default 1)
|
||||
* @param _inclusion_pin Digital pin that triggers inclusion mode, negative value disables functionality.
|
||||
* @param _rx Digital pin for receive led, negative value disables functionality.
|
||||
* @param _tx Digital pin for transfer led, negative value disables functionality.
|
||||
* @param _er Digital pin for error led, negative value disables functionality.
|
||||
*
|
||||
*/
|
||||
MyGateway(uint8_t _cepin=DEFAULT_CE_PIN, uint8_t _cspin=DEFAULT_CS_PIN, uint8_t _inclusion_time = 1, int8_t _inclusion_pin=-1, int8_t _rx=-1, int8_t _tx=-1, int8_t _er=-1);
|
||||
|
||||
/* Use this and pass a function that should be called when you want to process commands that arrive from radio network */
|
||||
void begin(rf24_pa_dbm_e paLevel=RF24_PA_LEVEL_GW, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE, void (*dataCallback)(char *)=NULL);
|
||||
|
||||
void processRadioMessage();
|
||||
void parseAndSend(char *inputString);
|
||||
|
||||
private:
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera
|
||||
unsigned long inclusionStartTime;
|
||||
boolean useWriteCallback;
|
||||
void (*dataCallback)(char *);
|
||||
int8_t pinInclusion;
|
||||
uint8_t inclusionTime;
|
||||
|
||||
uint8_t h2i(char c);
|
||||
|
||||
void serial(const char *fmt, ... );
|
||||
void serial(MyMessage &msg);
|
||||
void checkButtonTriggeredInclusion();
|
||||
void setInclusionMode(boolean newMode);
|
||||
void checkInclusionFinished();
|
||||
void ledTimers();
|
||||
void rxBlink(uint8_t cnt);
|
||||
void txBlink(uint8_t cnt);
|
||||
void errBlink(uint8_t cnt);
|
||||
};
|
||||
|
||||
void ledTimersInterrupt();
|
||||
void startInclusionInterrupt();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyHw.h"
|
||||
|
||||
MyHw::MyHw() {
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyHw_h
|
||||
#define MyHw_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "MyConfig.h"
|
||||
|
||||
/**
|
||||
* The Hw contains all hardware specific details of the platform
|
||||
*/
|
||||
|
||||
class MyHw
|
||||
{
|
||||
public:
|
||||
// MyHw constructor
|
||||
MyHw();
|
||||
/* // The following is defined as macros to save space
|
||||
virtual void init() = 0;
|
||||
virtual void watchdogReset() = 0;
|
||||
virtual void reboot() = 0;
|
||||
virtual unsigned long millisec() = 0;
|
||||
virtual uint8_t readConfig(uint8_t pos) = 0;
|
||||
virtual void writeConfig(uint8_t pos, uint8_t value) = 0;
|
||||
virtual void readConfigBlock(void* buf, void * pos, size_t length) = 0;
|
||||
virtual void writeConfigBlock(void* pos, void* buf, uint16_t length) = 0; */
|
||||
virtual void sleep(unsigned long ms) = 0;
|
||||
virtual bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) = 0;
|
||||
virtual uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) = 0;
|
||||
#ifdef DEBUG
|
||||
virtual void debugPrint(bool isGW, const char *fmt, ... ) = 0;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyHw.h"
|
||||
#include "MyHwATMega328.h"
|
||||
|
||||
int8_t pinIntTrigger = 0;
|
||||
void wakeUp() //place to send the interrupts
|
||||
{
|
||||
pinIntTrigger = 1;
|
||||
}
|
||||
void wakeUp2() //place to send the second interrupts
|
||||
{
|
||||
pinIntTrigger = 2;
|
||||
}
|
||||
|
||||
// Watchdog Timer interrupt service routine. This routine is required
|
||||
// to allow automatic WDIF and WDIE bit clearance in hardware.
|
||||
ISR (WDT_vect)
|
||||
{
|
||||
// WDIE & WDIF is cleared in hardware upon entering this ISR
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
MyHwATMega328::MyHwATMega328() : MyHw()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
// The following was redifined as macros to save space
|
||||
|
||||
inline uint8_t MyHwATMega328::readConfig(uint8_t pos) {
|
||||
return eeprom_read_byte((uint8_t*)pos);
|
||||
}
|
||||
|
||||
inline void MyHwATMega328::writeConfig(uint8_t pos, uint8_t value) {
|
||||
eeprom_update_byte((uint8_t*)pos, value);
|
||||
}
|
||||
|
||||
inline void MyHwATMega328::readConfigBlock(void* buf, void * pos, size_t length) {
|
||||
eeprom_read_block(buf, (void*)pos, length);
|
||||
}
|
||||
|
||||
inline void MyHwATMega328::writeConfigBlock(void* pos, void* buf, size_t length) {
|
||||
eeprom_write_block((void*)pos, (void*)buf, length);
|
||||
}
|
||||
|
||||
|
||||
inline void MyHwATMega328::init() {
|
||||
Serial.begin(BAUD_RATE);
|
||||
}
|
||||
|
||||
inline void MyHwATMega328::watchdogReset() {
|
||||
wdt_reset();
|
||||
}
|
||||
|
||||
inline void MyHwATMega328::reboot() {
|
||||
wdt_enable(WDTO_15MS); for (;;);
|
||||
}
|
||||
|
||||
inline unsigned long MyHwATMega328::millis() {
|
||||
return ::millis();
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void powerDown(period_t period) {
|
||||
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
#if defined __AVR_ATmega328P__
|
||||
do {
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
cli();
|
||||
sleep_enable();
|
||||
sleep_bod_disable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
sleep_disable();
|
||||
sei();
|
||||
} while (0);
|
||||
#else
|
||||
do {
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
cli();
|
||||
sleep_enable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
sleep_disable();
|
||||
sei();
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
void MyHwATMega328::internalSleep(unsigned long ms) {
|
||||
// Let serial prints finish (debug, log etc)
|
||||
Serial.flush();
|
||||
pinIntTrigger = 0;
|
||||
while (!pinIntTrigger && ms >= 8000) { powerDown(SLEEP_8S); ms -= 8000; }
|
||||
if (!pinIntTrigger && ms >= 4000) { powerDown(SLEEP_4S); ms -= 4000; }
|
||||
if (!pinIntTrigger && ms >= 2000) { powerDown(SLEEP_2S); ms -= 2000; }
|
||||
if (!pinIntTrigger && ms >= 1000) { powerDown(SLEEP_1S); ms -= 1000; }
|
||||
if (!pinIntTrigger && ms >= 500) { powerDown(SLEEP_500MS); ms -= 500; }
|
||||
if (!pinIntTrigger && ms >= 250) { powerDown(SLEEP_250MS); ms -= 250; }
|
||||
if (!pinIntTrigger && ms >= 125) { powerDown(SLEEP_120MS); ms -= 120; }
|
||||
if (!pinIntTrigger && ms >= 64) { powerDown(SLEEP_60MS); ms -= 60; }
|
||||
if (!pinIntTrigger && ms >= 32) { powerDown(SLEEP_30MS); ms -= 30; }
|
||||
if (!pinIntTrigger && ms >= 16) { powerDown(SLEEP_15Ms); ms -= 15; }
|
||||
}
|
||||
|
||||
void MyHwATMega328::sleep(unsigned long ms) {
|
||||
internalSleep(ms);
|
||||
}
|
||||
|
||||
bool MyHwATMega328::sleep(uint8_t interrupt, uint8_t mode, unsigned long ms) {
|
||||
// Let serial prints finish (debug, log etc)
|
||||
bool pinTriggeredWakeup = true;
|
||||
attachInterrupt(interrupt, wakeUp, mode);
|
||||
if (ms>0) {
|
||||
pinIntTrigger = 0;
|
||||
internalSleep(ms);
|
||||
if (0 == pinIntTrigger) {
|
||||
pinTriggeredWakeup = false;
|
||||
}
|
||||
} else {
|
||||
Serial.flush();
|
||||
powerDown(SLEEP_FOREVER);
|
||||
}
|
||||
detachInterrupt(interrupt);
|
||||
return pinTriggeredWakeup;
|
||||
}
|
||||
|
||||
inline uint8_t MyHwATMega328::sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms) {
|
||||
int8_t retVal = 1;
|
||||
attachInterrupt(interrupt1, wakeUp, mode1);
|
||||
attachInterrupt(interrupt2, wakeUp2, mode2);
|
||||
if (ms>0) {
|
||||
pinIntTrigger = 0;
|
||||
internalSleep(ms);
|
||||
if (0 == pinIntTrigger) {
|
||||
retVal = -1;
|
||||
}
|
||||
} else {
|
||||
Serial.flush();
|
||||
powerDown(SLEEP_FOREVER);
|
||||
}
|
||||
detachInterrupt(interrupt1);
|
||||
detachInterrupt(interrupt2);
|
||||
|
||||
if (1 == pinIntTrigger) {
|
||||
retVal = (int8_t)interrupt1;
|
||||
} else if (2 == pinIntTrigger) {
|
||||
retVal = (int8_t)interrupt2;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void MyHwATMega328::debugPrint(bool isGW, const char *fmt, ... ) {
|
||||
char fmtBuffer[300];
|
||||
if (isGW) {
|
||||
// prepend debug message to be handled correctly by controller (C_INTERNAL, I_LOG_MESSAGE)
|
||||
snprintf_P(fmtBuffer, 299, PSTR("0;0;%d;0;%d;"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
Serial.print(fmtBuffer);
|
||||
}
|
||||
va_list args;
|
||||
va_start (args, fmt );
|
||||
va_end (args);
|
||||
if (isGW) {
|
||||
// Truncate message if this is gateway node
|
||||
vsnprintf_P(fmtBuffer, 60, fmt, args);
|
||||
fmtBuffer[59] = '\n';
|
||||
fmtBuffer[60] = '\0';
|
||||
} else {
|
||||
vsnprintf_P(fmtBuffer, 299, fmt, args);
|
||||
}
|
||||
va_end (args);
|
||||
Serial.print(fmtBuffer);
|
||||
Serial.flush();
|
||||
|
||||
//Serial.write(freeRam());
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyHwATMega328_h
|
||||
#define MyHwATMega328_h
|
||||
|
||||
#include "MyHw.h"
|
||||
#include "MyConfig.h"
|
||||
#include "MyMessage.h"
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#endif
|
||||
|
||||
// Define these as macros to save valuable space
|
||||
#define hw_init() Serial.begin(BAUD_RATE)
|
||||
#define hw_watchdogReset() wdt_reset()
|
||||
#define hw_reboot() wdt_enable(WDTO_15MS); while (1)
|
||||
#define hw_millis() millis()
|
||||
#define hw_readConfig(__pos) (eeprom_read_byte((uint8_t*)(__pos)))
|
||||
#define hw_writeConfig(__pos, __value) (eeprom_update_byte((uint8_t*)(__pos), (__value)))
|
||||
#define hw_readConfigBlock(__buf, __pos, __length) (eeprom_read_block((__buf), (void*)(__pos), (__length)))
|
||||
#define hw_writeConfigBlock(__pos, __buf, __length) (eeprom_write_block((void*)(__pos), (void*)__buf, (__length)))
|
||||
|
||||
|
||||
|
||||
enum period_t
|
||||
{
|
||||
SLEEP_15Ms,
|
||||
SLEEP_30MS,
|
||||
SLEEP_60MS,
|
||||
SLEEP_120MS,
|
||||
SLEEP_250MS,
|
||||
SLEEP_500MS,
|
||||
SLEEP_1S,
|
||||
SLEEP_2S,
|
||||
SLEEP_4S,
|
||||
SLEEP_8S,
|
||||
SLEEP_FOREVER
|
||||
};
|
||||
|
||||
class MyHwATMega328 : public MyHw
|
||||
{
|
||||
public:
|
||||
MyHwATMega328();
|
||||
|
||||
/* void init();
|
||||
void watchdogReset();
|
||||
void reboot();
|
||||
unsigned long millis();
|
||||
uint8_t readConfig(uint8_t pos);
|
||||
void writeConfig(uint8_t pos, uint8_t value);
|
||||
void readConfigBlock(void* buf, void * pos, size_t length);
|
||||
void writeConfigBlock(void* pos, void* buf, size_t length); */
|
||||
|
||||
void sleep(unsigned long ms);
|
||||
bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms);
|
||||
uint8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms);
|
||||
#ifdef DEBUG
|
||||
void debugPrint(bool isGW, const char *fmt, ... );
|
||||
#endif
|
||||
private:
|
||||
void internalSleep(unsigned long ms);
|
||||
};
|
||||
#endif
|
||||
@@ -1,354 +0,0 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
Modified by Daniel Wiegert
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyMQTT.h"
|
||||
#include "utility/MsTimer2.h"
|
||||
|
||||
char V_0[] PROGMEM = "TEMP"; //V_TEMP
|
||||
char V_1[] PROGMEM = "HUM"; //V_HUM
|
||||
char V_2[] PROGMEM = "LIGHT"; //V_LIGHT
|
||||
char V_3[] PROGMEM = "DIMMER"; //V_DIMMER
|
||||
char V_4[] PROGMEM = "PRESSURE"; //V_PRESSURE
|
||||
char V_5[] PROGMEM = "FORECAST"; //V_FORECAST
|
||||
char V_6[] PROGMEM = "RAIN"; //V_RAIN
|
||||
char V_7[] PROGMEM = "RAINRATE"; //V_RAINRATE
|
||||
char V_8[] PROGMEM = "WIND"; //V_WIND
|
||||
char V_9[] PROGMEM = "GUST"; //V_GUST
|
||||
char V_10[] PROGMEM = "DIRECTON"; //V_DIRECTON
|
||||
char V_11[] PROGMEM = "UV"; //V_UV
|
||||
char V_12[] PROGMEM = "WEIGHT"; //V_WEIGHT
|
||||
char V_13[] PROGMEM = "DISTANCE"; //V_DISTANCE
|
||||
char V_14[] PROGMEM = "IMPEDANCE"; //V_IMPEDANCE
|
||||
char V_15[] PROGMEM = "ARMED"; //V_ARMED
|
||||
char V_16[] PROGMEM = "TRIPPED"; //V_TRIPPED
|
||||
char V_17[] PROGMEM = "WATT"; //V_WATT
|
||||
char V_18[] PROGMEM = "KWH"; //V_KWH
|
||||
char V_19[] PROGMEM = "SCENE_ON"; //V_SCENE_ON
|
||||
char V_20[] PROGMEM = "SCENE_OFF"; //V_SCENE_OFF
|
||||
char V_21[] PROGMEM = "HEATER"; //V_HEATER
|
||||
char V_22[] PROGMEM = "HEATER_SW"; //V_HEATER_SW
|
||||
char V_23[] PROGMEM = "LIGHT_LEVEL";//V_LIGHT_LEVEL
|
||||
char V_24[] PROGMEM = "VAR1"; //V_VAR1
|
||||
char V_25[] PROGMEM = "VAR2"; //V_VAR2
|
||||
char V_26[] PROGMEM = "VAR3"; //V_VAR3
|
||||
char V_27[] PROGMEM = "VAR4"; //V_VAR4
|
||||
char V_28[] PROGMEM = "VAR5"; //V_VAR5
|
||||
char V_29[] PROGMEM = "UP"; //V_UP
|
||||
char V_30[] PROGMEM = "DOWN"; //V_DOWN
|
||||
char V_31[] PROGMEM = "STOP"; //V_STOP
|
||||
char V_32[] PROGMEM = "IR_SEND"; //V_IR_SEND
|
||||
char V_33[] PROGMEM = "IR_RECEIVE"; //V_IR_RECEIVE
|
||||
char V_34[] PROGMEM = "FLOW"; //V_FLOW
|
||||
char V_35[] PROGMEM = "VOLUME"; //V_VOLUME
|
||||
char V_36[] PROGMEM = "LOCK_STATUS";//V_LOCK_STATUS
|
||||
char V_37[] PROGMEM = "DUST_LEVEL"; //V_DUST_LEVEL
|
||||
char V_38[] PROGMEM = "VOLTAGE"; //V_VOLTAGE
|
||||
char V_39[] PROGMEM = "CURRENT"; //V_CURRENT
|
||||
char V_40[] PROGMEM = ""; //
|
||||
char V_41[] PROGMEM = ""; //
|
||||
char V_42[] PROGMEM = ""; //
|
||||
char V_43[] PROGMEM = ""; //
|
||||
char V_44[] PROGMEM = ""; //
|
||||
char V_45[] PROGMEM = ""; //
|
||||
char V_46[] PROGMEM = ""; //
|
||||
char V_47[] PROGMEM = ""; //
|
||||
char V_48[] PROGMEM = ""; //
|
||||
char V_49[] PROGMEM = ""; //
|
||||
char V_50[] PROGMEM = ""; //
|
||||
char V_51[] PROGMEM = ""; //
|
||||
char V_52[] PROGMEM = ""; //
|
||||
char V_53[] PROGMEM = ""; //
|
||||
char V_54[] PROGMEM = ""; //
|
||||
char V_55[] PROGMEM = ""; //
|
||||
char V_56[] PROGMEM = ""; //
|
||||
char V_57[] PROGMEM = ""; //
|
||||
char V_58[] PROGMEM = ""; //
|
||||
char V_59[] PROGMEM = ""; //
|
||||
char V_60[] PROGMEM = "Started!\n"; //Custom for MQTTGateway
|
||||
char V_61[] PROGMEM = "SKETCH_NAME"; //Custom for MQTTGateway
|
||||
char V_62[] PROGMEM = "SKETCH_VERSION"; //Custom for MQTTGateway
|
||||
char V_63[] PROGMEM = "UNKNOWN"; //Custom for MQTTGateway
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
PROGMEM const char *vType[] = {
|
||||
V_0, V_1, V_2, V_3, V_4, V_5, V_6, V_7, V_8, V_9, V_10,
|
||||
V_11, V_12, V_13, V_14, V_15, V_16, V_17, V_18, V_19, V_20,
|
||||
V_21, V_22, V_23, V_24, V_25, V_26, V_27, V_28, V_29, V_30,
|
||||
V_31, V_32, V_33, V_34, V_35, V_36, V_37, V_38, V_39, V_40,
|
||||
V_41, V_42, V_43, V_44, V_45, V_46, V_47, V_48, V_49, V_50,
|
||||
V_51, V_52, V_53, V_54, V_55, V_56, V_57, V_58, V_59, V_60,
|
||||
V_61, V_62, V_63
|
||||
};
|
||||
|
||||
char broker[] PROGMEM = MQTT_BROKER_PREFIX;
|
||||
|
||||
#define S_FIRSTCUSTOM 60
|
||||
#define TYPEMAXLEN 20
|
||||
#define V_TOTAL (sizeof(vType)/sizeof(char *))-1
|
||||
|
||||
extern volatile uint8_t countRx;
|
||||
extern volatile uint8_t countTx;
|
||||
extern volatile uint8_t countErr;
|
||||
extern uint8_t pinRx;
|
||||
extern uint8_t pinTx;
|
||||
extern uint8_t pinEr;
|
||||
|
||||
MyMQTT::MyMQTT(uint8_t _cepin, uint8_t _cspin) :
|
||||
MySensor(_cepin, _cspin) {
|
||||
|
||||
}
|
||||
|
||||
inline MyMessage& build (MyMessage &msg, uint8_t sender, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
|
||||
msg.destination = destination;
|
||||
msg.sender = sender;
|
||||
msg.sensor = sensor;
|
||||
msg.type = type;
|
||||
mSetCommand(msg,command);
|
||||
mSetRequestAck(msg,enableAck);
|
||||
mSetAck(msg,false);
|
||||
return msg;
|
||||
}
|
||||
|
||||
char *MyMQTT::getType(char *b, const char **index) {
|
||||
char *q = b;
|
||||
char *p = (char *)pgm_read_word(index);
|
||||
while (*q++ = pgm_read_byte(p++));
|
||||
*q=0;
|
||||
return b;
|
||||
}
|
||||
|
||||
void MyMQTT::begin(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate, void (*inDataCallback)
|
||||
(const char *, uint8_t *), uint8_t _rx, uint8_t _tx, uint8_t _er) {
|
||||
Serial.begin(BAUD_RATE);
|
||||
repeaterMode = true;
|
||||
isGateway = true;
|
||||
MQTTClients = 0;
|
||||
|
||||
setupRepeaterMode();
|
||||
dataCallback = inDataCallback;
|
||||
|
||||
nc.nodeId = 0;
|
||||
nc.distance = 0;
|
||||
|
||||
// Start up the radio library
|
||||
setupRadio(paLevel, channel, dataRate);
|
||||
RF24::openReadingPipe(WRITE_PIPE, BASE_RADIO_ID);
|
||||
RF24::openReadingPipe(CURRENT_NODE_PIPE, BASE_RADIO_ID);
|
||||
RF24::startListening();
|
||||
|
||||
pinRx = _rx;
|
||||
pinMode(pinRx, OUTPUT);
|
||||
pinTx = _tx;
|
||||
pinMode(pinTx, OUTPUT);
|
||||
pinEr = _er;
|
||||
pinMode(pinEr, OUTPUT);
|
||||
|
||||
MsTimer2::set(200, ledTimersInterrupt);
|
||||
MsTimer2::start();
|
||||
|
||||
Serial.print(getType(convBuf, &vType[S_FIRSTCUSTOM]));
|
||||
}
|
||||
|
||||
void MyMQTT::processRadioMessage() {
|
||||
if (process()) {
|
||||
// A new message was received from one of the sensors
|
||||
MyMessage message = getLastMessage();
|
||||
rxBlink(1);
|
||||
|
||||
if (msg.isAck()) {
|
||||
Serial.println("msg is ack!");
|
||||
if (msg.sender == 255 && mGetCommand(msg) == C_INTERNAL && msg.type == I_ID_REQUEST) {
|
||||
// TODO: sending ACK request on id_response fucks node up. doesn't work.
|
||||
// The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS.
|
||||
}
|
||||
} else {
|
||||
// we have to check every message if its a newly assigned id or not.
|
||||
// Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable.
|
||||
uint8_t newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
|
||||
if (newNodeID <= MQTT_FIRST_SENSORID) {
|
||||
newNodeID = MQTT_FIRST_SENSORID;
|
||||
}
|
||||
if (msg.sender == newNodeID) {
|
||||
saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID);
|
||||
}
|
||||
|
||||
if (mGetCommand(msg) == C_INTERNAL) {
|
||||
if (msg.type == I_CONFIG) {
|
||||
txBlink(1);
|
||||
if (!sendRoute(build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, I_CONFIG, 0).set("M"))) {
|
||||
errBlink(1);
|
||||
}
|
||||
} else if (msg.type == I_ID_REQUEST && msg.sender == 255) {
|
||||
uint8_t newNodeID = loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
|
||||
if (newNodeID <= MQTT_FIRST_SENSORID) {
|
||||
newNodeID = MQTT_FIRST_SENSORID;
|
||||
}
|
||||
if (newNodeID >= MQTT_LAST_SENSORID) {
|
||||
// Sorry no more id's left :(
|
||||
newNodeID = AUTO;
|
||||
}
|
||||
txBlink(1);
|
||||
if (!sendRoute(build(msg, GATEWAY_ADDRESS, msg.sender, 255, C_INTERNAL, I_ID_RESPONSE, 0).set(newNodeID))) {
|
||||
errBlink(1);
|
||||
}
|
||||
}
|
||||
} else if (mGetCommand(msg)!= C_PRESENTATION) {
|
||||
// Pass along the message from sensors to MQTT
|
||||
SendMQTT(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyMQTT::processMQTTMessage(char *inputString, uint8_t inputPos) {
|
||||
char *str, *p, *payload=NULL;
|
||||
uint8_t i = 0;
|
||||
buffer[0]= 0;
|
||||
buffsize = 0;
|
||||
uint8_t mqttMsgType = (uint8_t)inputString[0] >> 4;
|
||||
|
||||
if (mqttMsgType == MQTTCONNECT) {
|
||||
buffer[buffsize++] = MQTTCONNACK << 4;
|
||||
buffer[buffsize++] = 0x02; // Remaining length
|
||||
buffer[buffsize++] = 0x00; // Connection accepted
|
||||
buffer[buffsize++] = 0x00; // Reserved
|
||||
MQTTClients++; // We have a new client connected!
|
||||
} else if (mqttMsgType == MQTTPINGREQ) {
|
||||
buffer[buffsize++] = MQTTPINGRESP << 4;
|
||||
buffer[buffsize++] = 0x00;
|
||||
} else if (mqttMsgType == MQTTSUBSCRIBE) {
|
||||
buffer[buffsize++] = MQTTSUBACK << 4; // Just ack everything, we actually dont really care!
|
||||
buffer[buffsize++] = 0x03; // Remaining length
|
||||
buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB
|
||||
buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB
|
||||
buffer[buffsize++] = MQTTQOS0; // QOS level
|
||||
} else if (mqttMsgType == MQTTUNSUBSCRIBE) {
|
||||
buffer[buffsize++] = MQTTUNSUBACK << 4;
|
||||
buffer[buffsize++] = 0x02; // Remaining length
|
||||
buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB
|
||||
buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB
|
||||
} else if (mqttMsgType == MQTTDISCONNECT) {
|
||||
MQTTClients--; // Client disconnected!
|
||||
}
|
||||
|
||||
if (buffsize > 0) {
|
||||
dataCallback(buffer, &buffsize);
|
||||
}
|
||||
|
||||
// We publish everything we get, we dont care if its subscribed or not!
|
||||
if (mqttMsgType == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && mqttMsgType == MQTTSUBSCRIBE)) {
|
||||
buffer[0] = 0;
|
||||
buffsize = 0;
|
||||
// Cut out address and payload depending on message type.
|
||||
if (mqttMsgType == MQTTSUBSCRIBE) {
|
||||
strncat(buffer, inputString+6, inputString[5]);
|
||||
} else {
|
||||
strncat(buffer, inputString+4, inputString[3]);
|
||||
}
|
||||
|
||||
// TODO: Check if we should send ack or not.
|
||||
for (str = strtok_r(buffer, "/", &p) ; str && i<4 ; str = strtok_r(NULL, "/", &p)) {
|
||||
if (i == 0) {
|
||||
//look for MQTT_BROKER_PREFIX
|
||||
if (strcmp_P(str, broker) != 0) {
|
||||
//Message not for us or malformatted!
|
||||
return;
|
||||
}
|
||||
} else if (i==1) {
|
||||
//NodeID
|
||||
msg.destination = atoi(str);
|
||||
} else if (i==2) {
|
||||
//SensorID
|
||||
msg.sensor = atoi(str);
|
||||
} else if (i==3) {
|
||||
//SensorType
|
||||
char match=0;
|
||||
|
||||
for (uint8_t j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(vType[j]))) ; j++) {
|
||||
//Strip V_ and compare
|
||||
if (strcmp((char*)&str[2], convBuf)==0) {
|
||||
match=j;
|
||||
break;
|
||||
}
|
||||
if (j >= V_TOTAL) { // No match found!
|
||||
match=V_TOTAL; // last item.
|
||||
break;
|
||||
}
|
||||
}
|
||||
msg.type = match;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// Check if package has payload
|
||||
if (mqttMsgType == MQTTPUBLISH) {
|
||||
uint8_t length = (uint8_t)inputString[1] - (uint8_t)(inputString[3]+2);
|
||||
if (length && length < MAX_PAYLOAD*2) {
|
||||
// Payload
|
||||
memcpy(convBuf, inputString+(inputString[3]+4), length);
|
||||
convBuf[length] = 0;
|
||||
payload = convBuf;
|
||||
}
|
||||
}
|
||||
msg.set(payload);
|
||||
|
||||
txBlink(1);
|
||||
if (!sendRoute(build(msg, GATEWAY_ADDRESS, msg.destination, msg.sensor, C_SET, msg.type, 0))) errBlink(1);
|
||||
}
|
||||
}
|
||||
|
||||
void MyMQTT::SendMQTT(MyMessage &msg) {
|
||||
buffsize = 0;
|
||||
if (!MQTTClients) {
|
||||
//We have no clients connected - return
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGetCommand(msg) == C_INTERNAL) {
|
||||
//Special message
|
||||
msg.type = msg.type+(S_FIRSTCUSTOM-10);
|
||||
}
|
||||
|
||||
buffer[buffsize++] = MQTTPUBLISH << 4; // 0:
|
||||
buffer[buffsize++] = 0x09; // 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2
|
||||
buffer[buffsize++] = 0x00; // 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!)
|
||||
buffer[buffsize++] = 0x08; // 3: Length LSB (ADDR), We'll set this later
|
||||
if (msg.type > V_TOTAL) {
|
||||
// If type > defined types set to unknown.
|
||||
msg.type=V_TOTAL;
|
||||
}
|
||||
strcpy_P(buffer+4, broker);
|
||||
buffsize+=strlen_P(broker);
|
||||
buffsize+=sprintf(&buffer[buffsize], "/%i/%i/V_%s", msg.sender, msg.sensor, getType(convBuf, &vType[msg.type]));
|
||||
buffer[3]=buffsize-4; // Set correct address length on byte 4.
|
||||
#ifdef DEBUG
|
||||
Serial.println((char*)&buffer[4]);
|
||||
#endif
|
||||
msg.getString(convBuf);
|
||||
for (uint8_t a=0; a<strlen(convBuf); a++) { // Payload
|
||||
buffer[buffsize++] = convBuf[a];
|
||||
}
|
||||
buffer[1]=buffsize-2; // Set correct Remaining length on byte 2.
|
||||
dataCallback(buffer, &buffsize);
|
||||
}
|
||||
|
||||
void MyMQTT::rxBlink(uint8_t cnt) {
|
||||
if(countRx == 255) { countRx = cnt; }
|
||||
}
|
||||
|
||||
void MyMQTT::txBlink(uint8_t cnt) {
|
||||
if(countTx == 255) { countTx = cnt; }
|
||||
}
|
||||
|
||||
void MyMQTT::errBlink(uint8_t cnt) {
|
||||
if(countErr == 255) { countErr = cnt; }
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
Modified by Daniel Wiegert
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyMQTT_h
|
||||
#define MyMQTT_h
|
||||
|
||||
#include "MySensor.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TCPDUMP // Dump TCP packages.
|
||||
#endif
|
||||
|
||||
#define MQTT_FIRST_SENSORID 20 // If you want manually configured nodes below this value. 255 = Disable
|
||||
#define MQTT_LAST_SENSORID 254 // 254 is max! 255 reserved.
|
||||
#define MQTT_BROKER_PREFIX "MyMQTT" // First prefix in MQTT tree, keep short!
|
||||
#define MQTT_SEND_SUBSCRIPTION 1 // Send empty payload (request) to node upon MQTT client subscribe request.
|
||||
// NOTE above : Beware to check if there is any length on payload in your incommingMessage code:
|
||||
// Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things.
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS)
|
||||
#define MQTT_MAX_PACKET_SIZE 100
|
||||
|
||||
#define MQTTPROTOCOLVERSION 3
|
||||
#define MQTTCONNECT 1 // Client request to connect to Server
|
||||
#define MQTTCONNACK 2 // Connect Acknowledgment
|
||||
#define MQTTPUBLISH 3 // Publish message
|
||||
#define MQTTPUBACK 4 // Publish Acknowledgment
|
||||
#define MQTTPUBREC 5 // Publish Received (assured delivery part 1)
|
||||
#define MQTTPUBREL 6 // Publish Release (assured delivery part 2)
|
||||
#define MQTTPUBCOMP 7 // Publish Complete (assured delivery part 3)
|
||||
#define MQTTSUBSCRIBE 8 // Client Subscribe request
|
||||
#define MQTTSUBACK 9 // Subscribe Acknowledgment
|
||||
#define MQTTUNSUBSCRIBE 10 // Client Unsubscribe request
|
||||
#define MQTTUNSUBACK 11 // Unsubscribe Acknowledgment
|
||||
#define MQTTPINGREQ 12 // PING Request
|
||||
#define MQTTPINGRESP 13 // PING Response
|
||||
#define MQTTDISCONNECT 14 // Client is Disconnecting
|
||||
#define MQTTReserved 15 // Reserved
|
||||
|
||||
#define MQTTQOS0 (0 << 1)
|
||||
#define MQTTQOS1 (1 << 1)
|
||||
#define MQTTQOS2 (2 << 1)
|
||||
|
||||
class MyMQTT :
|
||||
public MySensor {
|
||||
|
||||
public:
|
||||
MyMQTT(uint8_t _cepin=5, uint8_t _cspin=6);
|
||||
void begin(rf24_pa_dbm_e paLevel=RF24_PA_LEVEL_GW, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE, void (*dataCallback)
|
||||
(const char *, uint8_t *)=NULL, uint8_t _rx=6, uint8_t _tx=5, uint8_t _er=4 );
|
||||
void processRadioMessage();
|
||||
void processMQTTMessage(char *inputString, uint8_t inputPos);
|
||||
private:
|
||||
void (*dataCallback)(const char *, uint8_t *);
|
||||
void SendMQTT(MyMessage &msg);
|
||||
void ledTimers();
|
||||
void rxBlink(uint8_t cnt);
|
||||
void txBlink(uint8_t cnt);
|
||||
void errBlink(uint8_t cnt);
|
||||
|
||||
uint8_t MQTTClients;
|
||||
char buffer[MQTT_MAX_PACKET_SIZE];
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
uint8_t buffsize;
|
||||
char *getType(char *b, const char **index);
|
||||
};
|
||||
|
||||
extern void ledTimersInterrupt();
|
||||
|
||||
#endif
|
||||
Executable → Regular
+20
@@ -1,3 +1,23 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#include "MyMessage.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -1,14 +1,23 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MyMessage_h
|
||||
#define MyMessage_h
|
||||
|
||||
@@ -77,8 +86,8 @@ typedef enum {
|
||||
typedef enum {
|
||||
V_TEMP, // S_TEMP
|
||||
V_HUM, // S_HUM
|
||||
V_STATUS, // S_LIGHT, S_DIMMER, S_SPRINKLER, Used for setting binary (on/off) status. 1=on, 0=off
|
||||
V_LIGHT=2, // S_LIGHT, S_DIMMER. Same as V_STATUS
|
||||
V_STATUS, // S_LIGHT, S_DIMMER, S_SPRINKLER, S_HVAC, S_HEATER. Used for setting binary (on/off) status. 1=on, 0=off
|
||||
V_LIGHT=2, // Same as V_STATUS
|
||||
V_PERCENTAGE, // S_DIMMER. Used for sending a percentage value (0-100).
|
||||
V_DIMMER=3, // S_DIMMER. Same as V_PERCENTAGE.
|
||||
V_PRESSURE, // S_BARO
|
||||
@@ -101,7 +110,7 @@ typedef enum {
|
||||
V_HEATER, // Deprecated. Use V_HVAC_FLOW_STATE instead.
|
||||
V_HVAC_FLOW_STATE=21, // HVAC flow state ("Off", "HeatOn", "CoolOn", or "AutoChangeOver"). S_HEATER, S_HVAC
|
||||
V_HVAC_SPEED, // HVAC/Heater fan speed ("Min", "Normal", "Max", "Auto")
|
||||
V_LIGHT_LEVEL, // S_LIGHT_LEVEL (light level in uncalibrated percentage) or S_LEVEL (light level in lux)
|
||||
V_LIGHT_LEVEL, // Used for sending light level in uncalibrated percentage. See also V_LEVEL (light level in lux). S_LIGHT_LEVEL
|
||||
V_VAR1, V_VAR2, V_VAR3, V_VAR4, V_VAR5,
|
||||
V_UP, // S_COVER
|
||||
V_DOWN, // S_COVER
|
||||
@@ -125,7 +134,7 @@ typedef enum {
|
||||
V_UNIT_PREFIX, // Allows sensors to send in a string representing the
|
||||
// unit prefix to be displayed in GUI, not parsed by controller! E.g. cm, m, km, inch.
|
||||
// Can be used for S_DISTANCE or gas concentration (S_DUST, S_AIR_QUALITY)
|
||||
V_HVAC_SETPOINT_COLD, // HVAC cold setpoint (Integer between 0-100). S_HVAC
|
||||
V_HVAC_SETPOINT_COOL, // HVAC cool setpoint (Integer between 0-100). S_HVAC
|
||||
V_HVAC_SETPOINT_HEAT, // HVAC/Heater setpoint (Integer between 0-100). S_HEATER, S_HVAC
|
||||
V_HVAC_FLOW_MODE, // Flow mode for HVAC ("Auto", "ContinuousOn", "PeriodicOn"). S_HVAC
|
||||
|
||||
@@ -137,7 +146,7 @@ typedef enum {
|
||||
I_BATTERY_LEVEL, I_TIME, I_VERSION, I_ID_REQUEST, I_ID_RESPONSE,
|
||||
I_INCLUSION_MODE, I_CONFIG, I_FIND_PARENT, I_FIND_PARENT_RESPONSE,
|
||||
I_LOG_MESSAGE, I_CHILDREN, I_SKETCH_NAME, I_SKETCH_VERSION,
|
||||
I_REBOOT, I_GATEWAY_READY
|
||||
I_REBOOT, I_GATEWAY_READY, I_REQUEST_SIGNING, I_GET_NONCE, I_GET_NONCE_RESPONSE
|
||||
} mysensor_internal;
|
||||
|
||||
|
||||
@@ -167,8 +176,11 @@ typedef enum {
|
||||
#define BF_SET(y, x, start, len) ( y= ((y) &~ BF_MASK(start, len)) | BF_PREP(x, start, len) )
|
||||
|
||||
// Getters/setters for special bit fields in header
|
||||
#define mSetVersion(_msg,_version) BF_SET(_msg.version_length, _version, 0, 3)
|
||||
#define mGetVersion(_msg) BF_GET(_msg.version_length, 0, 3)
|
||||
#define mSetVersion(_msg,_version) BF_SET(_msg.version_length, _version, 0, 2)
|
||||
#define mGetVersion(_msg) BF_GET(_msg.version_length, 0, 2)
|
||||
|
||||
#define mSetSigned(_msg,_signed) BF_SET(_msg.version_length, _signed, 2, 1)
|
||||
#define mGetSigned(_msg) BF_GET(_msg.version_length, 2, 1)
|
||||
|
||||
#define mSetLength(_msg,_length) BF_SET(_msg.version_length, _length, 3, 5)
|
||||
#define mGetLength(_msg) BF_GET(_msg.version_length, 3, 5)
|
||||
@@ -262,7 +274,8 @@ struct
|
||||
uint8_t sender; // 8 bit - Id of sender node (origin)
|
||||
uint8_t destination; // 8 bit - Id of destination node
|
||||
|
||||
uint8_t version_length; // 3 bit - Protocol version
|
||||
uint8_t version_length; // 2 bit - Protocol version
|
||||
// 1 bit - Signed flag
|
||||
// 5 bit - Length of payload
|
||||
uint8_t command_ack_payload; // 3 bit - Command type
|
||||
// 1 bit - Request an ack - Indicator that receiver should send an ack back.
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyParser.h"
|
||||
|
||||
MyParser::MyParser() {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyParser_h
|
||||
#define MyParser_h
|
||||
|
||||
#include "MyMessage.h"
|
||||
|
||||
class MyParser
|
||||
{
|
||||
public:
|
||||
// MyParser constructor
|
||||
MyParser();
|
||||
// parse(message, inputString)
|
||||
// parse a string into a message element
|
||||
// returns true if successfully parsed the input string
|
||||
virtual bool parse(MyMessage &message, char *inputString) = 0;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyParser.h"
|
||||
#include "MyParserSerial.h"
|
||||
#include "MyTransport.h"
|
||||
|
||||
MyParserSerial::MyParserSerial() : MyParser() {}
|
||||
|
||||
bool MyParserSerial::parse(MyMessage &message, char *inputString) {
|
||||
char *str, *p, *value=NULL;
|
||||
uint8_t bvalue[MAX_PAYLOAD];
|
||||
uint8_t blen = 0;
|
||||
int i = 0;
|
||||
uint8_t command = 0;
|
||||
uint8_t ack = 0;
|
||||
|
||||
// Extract command data coming on serial line
|
||||
for (str = strtok_r(inputString, ";", &p); // split using semicolon
|
||||
str && i < 6; // loop while str is not null an max 5 times
|
||||
str = strtok_r(NULL, ";", &p) // get subsequent tokens
|
||||
) {
|
||||
switch (i) {
|
||||
case 0: // Radioid (destination)
|
||||
message.destination = atoi(str);
|
||||
break;
|
||||
case 1: // Childid
|
||||
message.sensor = atoi(str);
|
||||
break;
|
||||
case 2: // Message type
|
||||
command = atoi(str);
|
||||
mSetCommand(message, command);
|
||||
break;
|
||||
case 3: // Should we request ack from destination?
|
||||
ack = atoi(str);
|
||||
break;
|
||||
case 4: // Data type
|
||||
message.type = atoi(str);
|
||||
break;
|
||||
case 5: // Variable value
|
||||
if (command == C_STREAM) {
|
||||
blen = 0;
|
||||
uint8_t val;
|
||||
while (*str) {
|
||||
val = h2i(*str++) << 4;
|
||||
val += h2i(*str++);
|
||||
bvalue[blen] = val;
|
||||
blen++;
|
||||
}
|
||||
} else {
|
||||
value = str;
|
||||
// Remove ending carriage return character (if it exists)
|
||||
uint8_t lastCharacter = strlen(value)-1;
|
||||
if (value[lastCharacter] == '\r')
|
||||
value[lastCharacter] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// Check for invalid input
|
||||
if (i < 5)
|
||||
return false;
|
||||
|
||||
message.sender = GATEWAY_ADDRESS;
|
||||
message.last = GATEWAY_ADDRESS;
|
||||
mSetRequestAck(message, ack?1:0);
|
||||
mSetAck(message, false);
|
||||
if (command == C_STREAM)
|
||||
message.set(bvalue, blen);
|
||||
else
|
||||
message.set(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t MyParserSerial::h2i(char c) {
|
||||
uint8_t i = 0;
|
||||
if (c <= '9')
|
||||
i += c - '0';
|
||||
else if (c >= 'a')
|
||||
i += c - 'a' + 10;
|
||||
else
|
||||
i += c - 'A' + 10;
|
||||
return i;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyParserSerial_h
|
||||
#define MyParserSerial_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MyParser.h"
|
||||
|
||||
class MyParserSerial : public MyParser
|
||||
{
|
||||
public:
|
||||
MyParserSerial();
|
||||
bool parse(MyMessage &message, char *inputString);
|
||||
private:
|
||||
uint8_t h2i(char c);
|
||||
};
|
||||
#endif
|
||||
Executable → Regular
+645
-356
File diff suppressed because it is too large
Load Diff
+162
-67
@@ -1,44 +1,57 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MySensor_h
|
||||
#define MySensor_h
|
||||
|
||||
#include "Version.h" // Auto generated by bot
|
||||
#include "MyConfig.h"
|
||||
#include "MyHw.h"
|
||||
#include "MyTransport.h"
|
||||
#include "MyTransportNRF24.h"
|
||||
#include "MyParser.h"
|
||||
#ifdef MY_SIGNING_FEATURE
|
||||
#include "MySigning.h"
|
||||
#include "MySigningNone.h"
|
||||
#endif
|
||||
#include "MyMessage.h"
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
#include "utility/SPIFlash.h"
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#include "utility/LowPower.h"
|
||||
#include "utility/RF24.h"
|
||||
#include "utility/RF24_config.h"
|
||||
#endif
|
||||
|
||||
// Set the hardware driver to use (initialized by MySensor-class)
|
||||
//#if defined __AVR_ATmega328P__
|
||||
#include "MyHwATMega328.h"
|
||||
typedef MyHwATMega328 MyHwDriver;
|
||||
//#endif
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
#define debug(x,...) debugPrint(x, ##__VA_ARGS__)
|
||||
#define debug(x,...) hw.debugPrint(isGateway, x, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debug(x,...)
|
||||
#endif
|
||||
|
||||
#define BAUD_RATE 115200
|
||||
|
||||
#define AUTO 0xFF // 0-254. Id 255 is reserved for auto initialization of nodeId.
|
||||
#define NODE_SENSOR_ID 0xFF // Node child id is always created for when a node
|
||||
|
||||
// EEPROM start address for mysensors library data
|
||||
#define EEPROM_START 0
|
||||
@@ -54,20 +67,13 @@
|
||||
#define EEPROM_FIRMWARE_VERSION_ADDRESS (EEPROM_FIRMWARE_TYPE_ADDRESS+2)
|
||||
#define EEPROM_FIRMWARE_BLOCKS_ADDRESS (EEPROM_FIRMWARE_VERSION_ADDRESS+2)
|
||||
#define EEPROM_FIRMWARE_CRC_ADDRESS (EEPROM_FIRMWARE_BLOCKS_ADDRESS+2)
|
||||
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2) // First free address for sketch static configuration
|
||||
|
||||
// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data).
|
||||
#define GATEWAY_ADDRESS ((uint8_t)0)
|
||||
#define BROADCAST_ADDRESS ((uint8_t)0xFF)
|
||||
#define TO_ADDR(x) (BASE_RADIO_ID + x)
|
||||
|
||||
#define WRITE_PIPE ((uint8_t)0)
|
||||
#define CURRENT_NODE_PIPE ((uint8_t)1)
|
||||
#define BROADCAST_PIPE ((uint8_t)2)
|
||||
#define EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS (EEPROM_FIRMWARE_CRC_ADDRESS+2)
|
||||
#define EEPROM_LOCAL_CONFIG_ADDRESS (EEPROM_SIGNING_REQUIREMENT_TABLE_ADDRESS+32) // First free address for sketch static configuration
|
||||
|
||||
// Search for a new parent node after this many transmission failures
|
||||
#define SEARCH_FAILURES 5
|
||||
|
||||
|
||||
struct NodeConfig
|
||||
{
|
||||
uint8_t nodeId; // Current node id
|
||||
@@ -79,8 +85,55 @@ struct ControllerConfig {
|
||||
uint8_t isMetric;
|
||||
};
|
||||
|
||||
|
||||
// Size of each firmware block
|
||||
#define FIRMWARE_BLOCK_SIZE 16
|
||||
// Number of times a firmware block should be requested before giving up
|
||||
#define FIRMWARE_MAX_REQUESTS 5
|
||||
// Number of times to request a fw block before giving up
|
||||
#define MY_OTA_RETRY 5
|
||||
// Number of millisecons before re-request a fw block
|
||||
#define MY_OTA_RETRY_DELAY 500
|
||||
// Start offset for firmware in flash (DualOptiboot wants to keeps a signature first)
|
||||
#define FIRMWARE_START_OFFSET 10
|
||||
// Bootloader version
|
||||
#define MY_OTA_BOOTLOADER_MAJOR_VERSION 3
|
||||
#define MY_OTA_BOOTLOADER_MINOR_VERSION 0
|
||||
#define MY_OTA_BOOTLOADER_VERSION (MY_OTA_BOOTLOADER_MINOR_VERSION * 256 + MY_OTA_BOOTLOADER_MAJOR_VERSION)
|
||||
|
||||
|
||||
// FW config structure, stored in eeprom
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t blocks;
|
||||
uint16_t crc;
|
||||
} __attribute__((packed)) NodeFirmwareConfig;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t blocks;
|
||||
uint16_t crc;
|
||||
uint16_t BLVersion;
|
||||
} __attribute__((packed)) RequestFirmwareConfig;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t block;
|
||||
} __attribute__((packed)) RequestFWBlock;
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
uint16_t version;
|
||||
uint16_t block;
|
||||
uint8_t data[FIRMWARE_BLOCK_SIZE];
|
||||
} __attribute__((packed)) ReplyFWBlock;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class MySensor : public RF24
|
||||
class MySensor
|
||||
{
|
||||
public:
|
||||
/**
|
||||
@@ -88,10 +141,18 @@ class MySensor : public RF24
|
||||
*
|
||||
* Creates a new instance of Sensor class.
|
||||
*
|
||||
* @param _cepin The pin attached to RF24 Chip Enable on the RF module (default 9)
|
||||
* @param _cspin The pin attached to RF24 Chip Select (default 10)
|
||||
*/
|
||||
MySensor(uint8_t _cepin=DEFAULT_CE_PIN, uint8_t _cspin=DEFAULT_CS_PIN);
|
||||
MySensor(MyTransport &radio =*new MyTransportNRF24(), MyHw &hw=*new MyHwDriver()
|
||||
#ifdef MY_SIGNING_FEATURE
|
||||
, MySigning &signer=*new MySigningNone()
|
||||
#endif
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
, uint8_t _rx=DEFAULT_RX_LED_PIN,
|
||||
uint8_t _tx=DEFAULT_TX_LED_PIN,
|
||||
uint8_t _er=DEFAULT_ERR_LED_PIN,
|
||||
unsigned long _blink_period=DEFAULT_LED_BLINK_PERIOD
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
* Begin operation of the MySensors library
|
||||
@@ -101,12 +162,9 @@ class MySensor : public RF24
|
||||
* @param nodeId The unique id (1-254) for this sensor. Default is AUTO(255) which means sensor tries to fetch an id from controller.
|
||||
* @param repeaterMode Activate repeater mode. This node will forward messages to other nodes in the radio network. Make sure to call process() regularly. Default in false
|
||||
* @param parentNodeId Use this to force node to always communicate with a certain parent node. Default is AUTO which means node automatically tries to find a parent.
|
||||
* @param paLevel Radio PA Level for this sensor. Default RF24_PA_MAX
|
||||
* @param channel Radio channel. Default is channel 76
|
||||
* @param dataRate Radio transmission speed. Default RF24_1MBPS
|
||||
*/
|
||||
|
||||
void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, uint8_t parentNodeId=AUTO, rf24_pa_dbm_e paLevel=RF24_PA_LEVEL, uint8_t channel=RF24_CHANNEL, rf24_datarate_e dataRate=RF24_DATARATE);
|
||||
void begin(void (* msgCallback)(const MyMessage &)=NULL, uint8_t nodeId=AUTO, boolean repeaterMode=false, uint8_t parentNodeId=AUTO);
|
||||
|
||||
/**
|
||||
* Return the nodes nodeId.
|
||||
@@ -119,6 +177,7 @@ class MySensor : public RF24
|
||||
*
|
||||
* @param sensorId Select a unique sensor id for this sensor. Choose a number between 0-254.
|
||||
* @param sensorType The sensor type. See sensor typedef in MyMessage.h.
|
||||
* @param description A textual description of the sensor.
|
||||
* @param ack Set this to true if you want destination node to send ack back to this node. Default is not to request any ack.
|
||||
* @param description A textual description of the sensor.
|
||||
*/
|
||||
@@ -142,6 +201,8 @@ class MySensor : public RF24
|
||||
*/
|
||||
bool send(MyMessage &msg, bool ack=false);
|
||||
|
||||
boolean sendRoute(MyMessage &message);
|
||||
|
||||
/**
|
||||
* Send this nodes battery level to gateway.
|
||||
* @param level Level between 0-100(%)
|
||||
@@ -185,7 +246,7 @@ class MySensor : public RF24
|
||||
* power cycles.
|
||||
*
|
||||
* You have 256 bytes to play with. Note that there is a limitation on the number
|
||||
* of writes the EEPROM can handle (~100 000 cycles).
|
||||
* of writes the EEPROM can handle (~100 000 cycles on ATMega328).
|
||||
*
|
||||
* @param pos The position to store value in (0-255)
|
||||
* @param Value to store in position
|
||||
@@ -205,11 +266,7 @@ class MySensor : public RF24
|
||||
*/
|
||||
MyMessage& getLastMessage(void);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the Arduino and radio. Wake up on timer.
|
||||
* @param ms Number of milliseconds to sleep.
|
||||
*/
|
||||
void sleep(unsigned long ms);
|
||||
|
||||
|
||||
/**
|
||||
* Wait for a specified amount of time to pass. Keeps process()ing.
|
||||
@@ -221,7 +278,13 @@ class MySensor : public RF24
|
||||
void wait(unsigned long ms);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the Arduino and radio. Wake up on timer or pin change.
|
||||
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer.
|
||||
* @param ms Number of milliseconds to sleep.
|
||||
*/
|
||||
void sleep(unsigned long ms);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change.
|
||||
* See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin
|
||||
* is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3
|
||||
* @param interrupt Interrupt that should trigger the wakeup
|
||||
@@ -232,7 +295,7 @@ class MySensor : public RF24
|
||||
bool sleep(uint8_t interrupt, uint8_t mode, unsigned long ms=0);
|
||||
|
||||
/**
|
||||
* Sleep (PowerDownMode) the Arduino and radio. Wake up on timer or pin change for two separate interrupts.
|
||||
* Sleep (PowerDownMode) the MCU and radio. Wake up on timer or pin change for two separate interrupts.
|
||||
* See: http://arduino.cc/en/Reference/attachInterrupt for details on modes and which pin
|
||||
* is assigned to what interrupt. On Nano/Pro Mini: 0=Pin2, 1=Pin3
|
||||
* @param interrupt1 First interrupt that should trigger the wakeup
|
||||
@@ -244,45 +307,77 @@ class MySensor : public RF24
|
||||
*/
|
||||
int8_t sleep(uint8_t interrupt1, uint8_t mode1, uint8_t interrupt2, uint8_t mode2, unsigned long ms=0);
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
void debugPrint(const char *fmt, ... );
|
||||
int freeRam();
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
/**
|
||||
* Blink with LEDs
|
||||
* @param cnt how many blink cycles to keep the LED on. Default cycle is 300ms
|
||||
*/
|
||||
void rxBlink(uint8_t cnt);
|
||||
void txBlink(uint8_t cnt);
|
||||
void errBlink(uint8_t cnt);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
NodeConfig nc; // Essential settings for node to work
|
||||
ControllerConfig cc; // Configuration coming from controller
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
NodeFirmwareConfig fc;
|
||||
bool fwUpdateOngoing;
|
||||
unsigned long fwLastRequestTime;
|
||||
uint16_t fwBlock;
|
||||
uint8_t fwRetry;
|
||||
SPIFlash flash;
|
||||
#endif
|
||||
|
||||
bool repeaterMode;
|
||||
bool autoFindParent;
|
||||
bool isGateway;
|
||||
MyMessage msg; // Buffer for incoming messages.
|
||||
MyMessage ack; // Buffer for ack messages.
|
||||
|
||||
void setupRepeaterMode();
|
||||
void setupRadio(rf24_pa_dbm_e paLevel, uint8_t channel, rf24_datarate_e dataRate);
|
||||
boolean sendRoute(MyMessage &message);
|
||||
boolean sendWrite(uint8_t dest, MyMessage &message, bool broadcast=false);
|
||||
MyMessage msg; // Buffer for incoming messages.
|
||||
MyMessage tmpMsg ; // Buffer for temporary messages (acks and nonces among others).
|
||||
#ifdef MY_SIGNING_FEATURE
|
||||
uint16_t doSign[16]; // Bitfield indicating which sensors require signed communication
|
||||
MyMessage msgSign; // Buffer for message to sign.
|
||||
MySigning& signer;
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
uint8_t pinRx; // Rx led pin
|
||||
uint8_t pinTx; // Tx led pin
|
||||
uint8_t pinEr; // Err led pin
|
||||
|
||||
// these variables don't need to be volatile, since we are not using interrupts
|
||||
uint8_t countRx;
|
||||
uint8_t countTx;
|
||||
uint8_t countErr;
|
||||
|
||||
unsigned long ledBlinkPeriod;
|
||||
void handleLedsBlinking(); // do the actual blinking
|
||||
#endif
|
||||
|
||||
MyTransport& radio;
|
||||
MyHw& hw;
|
||||
|
||||
boolean sendWrite(uint8_t dest, MyMessage &message);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
#endif
|
||||
uint8_t failedTransmissions;
|
||||
uint8_t *childNodeTable; // In memory buffer for routing information to other nodes. also stored in EEPROM
|
||||
void (*timeCallback)(unsigned long); // Callback for requested time messages
|
||||
void (*msgCallback)(const MyMessage &); // Callback for incoming messages from other nodes and gateway.
|
||||
|
||||
#ifdef MY_OTA_FIRMWARE_FEATURE
|
||||
// do a crc16 on the whole received firmware
|
||||
bool isValidFirmware();
|
||||
#endif
|
||||
|
||||
|
||||
void requestNodeId();
|
||||
void setupNode();
|
||||
void findParentNode();
|
||||
uint8_t crc8Message(MyMessage &message);
|
||||
uint8_t getChildRoute(uint8_t childId);
|
||||
void addChildRoute(uint8_t childId, uint8_t route);
|
||||
void removeChildRoute(uint8_t childId);
|
||||
void internalSleep(unsigned long ms);
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MySigning.h"
|
||||
|
||||
MySigning::MySigning(bool requestSignatures) : _requestSignatures(requestSignatures) {
|
||||
}
|
||||
|
||||
|
||||
bool MySigning::requestSignatures() {
|
||||
return _requestSignatures;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* The MySigning driver provides a generic API for various signing backends to offer
|
||||
* signing of MySensors messages.
|
||||
*
|
||||
*/
|
||||
#ifndef MySigning_h
|
||||
#define MySigning_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include "MyMessage.h"
|
||||
|
||||
class MySigning
|
||||
{
|
||||
public:
|
||||
// MySigning constructor.
|
||||
// Different parameters would be needed depending on signing backend (e.g. pins connected etc.).
|
||||
// Keeping these parameters as #define's in MyConfig to streamline the driver interface.
|
||||
// @param requestSignatures Set this to true if you want destination node to sign all messages sent to this node. Default is not to require signing.
|
||||
MySigning(bool requestSignatures=false);
|
||||
|
||||
// Returns the current requestSignature setting
|
||||
bool requestSignatures();
|
||||
|
||||
// Stores signing identifier and a new nonce in provided message for signing operations.
|
||||
// All space in message payload buffer is used for signing identifier and nonce.
|
||||
// Returns false if subsystem is busy processing an ongoing signing operation.
|
||||
// If successful, this marks the start of a signing operation at the receiving side so
|
||||
// implementation is expected to do any necessary initializations within this call.
|
||||
virtual bool getNonce(MyMessage &msg) = 0;
|
||||
|
||||
// Check timeout of verification session.
|
||||
// Nonce will be purged if it takes too long for a signed message to be sent to the receiver.
|
||||
// This function should be called on regular intervals.
|
||||
virtual bool checkTimer(void) = 0;
|
||||
|
||||
// Get nonce from provided message and store for signing operations.
|
||||
// Returns false if subsystem is busy processing an ongoing signing operation.
|
||||
// Returns false if signing identifier found in message is not supported by the used backend.
|
||||
// If successful, this marks the start of a signing operation at the sending side so
|
||||
// implementation is expected to do any necessary initializations within this call.
|
||||
virtual bool putNonce(MyMessage &msg) = 0;
|
||||
|
||||
// Signs provided message. All remaining space in message payload buffer is used for signing
|
||||
// identifier and signature.
|
||||
// Nonce used for signature calculation is the one generated previously using getNonce().
|
||||
// Nonce will be cleared when this function is called to prevent re-use of nonce.
|
||||
// Returns false if subsystem is busy processing an ongoing signing operation.
|
||||
// Returns false if not two bytes or more of free payload space is left in provided message.
|
||||
// This ends a signing operation at the sending side so implementation is expected to do any
|
||||
// deinitializations and enter a power saving state within this call.
|
||||
virtual bool signMsg(MyMessage &msg) = 0;
|
||||
|
||||
// Verifies signature in provided message.
|
||||
// Nonce used for verification is the one previously set using putNonce().
|
||||
// Nonce will be cleared when this function is called to prevent re-use of nonce.
|
||||
// Returns false if subsystem is busy processing an ongoing signing operation.
|
||||
// Returns false if signing identifier found in message is not supported by the used backend.
|
||||
// This ends a signing operation at the receiving side so implementation is expected to do any
|
||||
// deinitializations and enter a power saving state within this call.
|
||||
virtual bool verifyMsg(MyMessage &msg) = 0;
|
||||
|
||||
public:
|
||||
bool _requestSignatures;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* ATSHA204 signing backend. The Atmel ATSHA204 offers true random number generation and
|
||||
* HMAC-SHA256 authentication with a readout-protected key.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MySigning.h"
|
||||
#include "MySigningAtsha204.h"
|
||||
|
||||
// Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected)
|
||||
//#define DEBUG_SIGNING
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
#define DEBUG_SIGNING_PRINTLN(args) Serial.println(args)
|
||||
#else
|
||||
#define DEBUG_SIGNING_PRINTLN(args)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
Serial.println(str);
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
if (buf[i] < 0x10)
|
||||
{
|
||||
Serial.print('0'); // Because Serial.print does not 0-pad HEX
|
||||
}
|
||||
Serial.print(buf[i], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#else
|
||||
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
||||
#endif
|
||||
|
||||
|
||||
MySigningAtsha204::MySigningAtsha204(bool requestSignatures,
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t nof_whitelist_entries, const whitelist_entry_t* the_whitelist,
|
||||
#endif
|
||||
uint8_t atshaPin)
|
||||
:
|
||||
MySigning(requestSignatures),
|
||||
atsha204(atshaPin),
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
whitelist(the_whitelist),
|
||||
whitlist_sz(nof_whitelist_entries),
|
||||
#endif
|
||||
verification_ongoing(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool MySigningAtsha204::getNonce(MyMessage &msg) {
|
||||
// Generate random number for use as nonce
|
||||
// We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value
|
||||
// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (atsha204.sha204m_execute(SHA204_RANDOM, RANDOM_NO_SEED_UPDATE, 0, 0, NULL,
|
||||
RANDOM_COUNT, tx_buffer, RANDOM_RSP_SIZE, rx_buffer) != SHA204_SUCCESS) {
|
||||
DEBUG_SIGNING_PRINTLN(F("FTGN")); // FTGN = Failed to generate nonce
|
||||
return false;
|
||||
}
|
||||
current_nonce[i] = rx_buffer[SHA204_BUFFER_POS_DATA];
|
||||
}
|
||||
memcpy(current_nonce, sha256(current_nonce, 32), MAX_PAYLOAD);
|
||||
|
||||
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
|
||||
memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD);
|
||||
|
||||
// Replace the first byte in the nonce with our signing identifier
|
||||
current_nonce[0] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Transfer the first part of the nonce to the message
|
||||
msg.set(current_nonce, MAX_PAYLOAD);
|
||||
verification_ongoing = true;
|
||||
timestamp = millis(); // Set timestamp to determine when to purge nonce
|
||||
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
||||
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
||||
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
||||
if (timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) timestamp = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204::checkTimer() {
|
||||
if (verification_ongoing) {
|
||||
if (millis() < timestamp || millis() > timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
DEBUG_SIGNING_PRINTLN(F("VT")); // VT = Verification timeout
|
||||
// Purge nonce
|
||||
memset(current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||
verification_ongoing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204::putNonce(MyMessage &msg) {
|
||||
if (((uint8_t*)msg.getCustom())[0] != SIGNING_IDENTIFIER) {
|
||||
DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
|
||||
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
|
||||
memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204::signMsg(MyMessage &msg) {
|
||||
// If we cannot fit any signature in the message, refuse to sign it
|
||||
if (mGetLength(msg) > MAX_PAYLOAD-2) {
|
||||
DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate signature of message
|
||||
mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
|
||||
calculateSignature(msg);
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
// Salt the signature with the senders nodeId and the unique serial of the ATSHA device
|
||||
memcpy(current_nonce, &rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
current_nonce[32] = msg.sender;
|
||||
atsha204.getSerialNumber(¤t_nonce[33]);
|
||||
(void)sha256(current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
DEBUG_SIGNING_PRINTLN(F("SWS")); // SWS = Signature whitelist salted
|
||||
#endif
|
||||
|
||||
// Overwrite the first byte in the signature with the signing identifier
|
||||
rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Transfer as much signature data as the remaining space in the message permits
|
||||
memcpy(&msg.data[mGetLength(msg)], &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204::verifyMsg(MyMessage &msg) {
|
||||
if (!verification_ongoing) {
|
||||
DEBUG_SIGNING_PRINTLN(F("NAVS")); // NAVS = No active verification session
|
||||
return false;
|
||||
} else {
|
||||
// Make sure we have not expired
|
||||
if (!checkTimer()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
verification_ongoing = false;
|
||||
|
||||
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
||||
DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_SIGNING_PRINTBUF(F("SIM:"), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); // SIM = Signature in message
|
||||
calculateSignature(msg); // Get signature of message
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
// Look up the senders nodeId in our whitelist and salt the signature with that data
|
||||
for (int j=0; j < whitlist_sz; j++) {
|
||||
if (whitelist[j].nodeId == msg.sender) {
|
||||
DEBUG_SIGNING_PRINTLN(F("SIW")); // SIW = Sender found in whitelist
|
||||
memcpy(current_nonce, &rx_buffer[SHA204_BUFFER_POS_DATA], 32); // We can reuse the nonce buffer now since it is no longer needed
|
||||
current_nonce[32] = msg.sender;
|
||||
memcpy(¤t_nonce[33], whitelist[j].serial, SHA204_SERIAL_SZ);
|
||||
(void)sha256(current_nonce, 32+1+SHA204_SERIAL_SZ); // we can 'void' sha256 because the hash is already put in the correct place
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overwrite the first byte in the signature with the signing identifier
|
||||
rx_buffer[SHA204_BUFFER_POS_DATA] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Compare the caluclated signature with the provided signature
|
||||
if (memcmp(&msg.data[mGetLength(msg)], &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg))) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("SNOK:"), &rx_buffer[SHA204_BUFFER_POS_DATA], MAX_PAYLOAD-mGetLength(msg)); // SNOK = Signature bad
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
DEBUG_SIGNING_PRINTLN(F("W?")); // W? = Is the sender whitelisted?
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
DEBUG_SIGNING_PRINTLN(F("SOK")); // SOK = Signature OK
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to calculate signature of msg (returned in rx_buffer[SHA204_BUFFER_POS_DATA])
|
||||
void MySigningAtsha204::calculateSignature(MyMessage &msg) {
|
||||
memset(temp_message, 0, 32);
|
||||
memcpy(temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
|
||||
// Program the data to sign into the ATSHA204
|
||||
DEBUG_SIGNING_PRINTBUF(F("MSG:"), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); // MSG = Message to sign
|
||||
DEBUG_SIGNING_PRINTBUF(F("CNC:"), current_nonce, 32); // CNC = Current nonce
|
||||
(void)atsha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG, 8 << 3, 32, temp_message,
|
||||
WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
|
||||
|
||||
// Program the nonce to use for the signature (has to be done just before GENDIG due to chip limitations)
|
||||
(void)atsha204.sha204m_execute(SHA204_NONCE, NONCE_MODE_PASSTHROUGH, 0, NONCE_NUMIN_SIZE_PASSTHROUGH, current_nonce,
|
||||
NONCE_COUNT_LONG, tx_buffer, NONCE_RSP_SIZE_SHORT, rx_buffer);
|
||||
|
||||
// Purge nonce when used
|
||||
memset(current_nonce, 0x00, NONCE_NUMIN_SIZE_PASSTHROUGH);
|
||||
|
||||
// Generate digest of data and nonce
|
||||
(void)atsha204.sha204m_execute(SHA204_GENDIG, GENDIG_ZONE_DATA, 8, 0, NULL,
|
||||
GENDIG_COUNT_DATA, tx_buffer, GENDIG_RSP_SIZE, rx_buffer);
|
||||
|
||||
// Calculate HMAC of message+nonce digest and secret key
|
||||
(void)atsha204.sha204m_execute(SHA204_HMAC, HMAC_MODE_SOURCE_FLAG_MATCH, 0, 0, NULL,
|
||||
HMAC_COUNT, tx_buffer, HMAC_RSP_SIZE, rx_buffer);
|
||||
|
||||
// Put device back to sleep
|
||||
atsha204.sha204c_sleep();
|
||||
|
||||
DEBUG_SIGNING_PRINTBUF(F("HMAC:"), &rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
||||
}
|
||||
|
||||
// Helper to calculate a generic SHA256 digest of provided buffer (only supports one block)
|
||||
// The pointer to the hash is returned, but the hash is also stored in rx_buffer[SHA204_BUFFER_POS_DATA])
|
||||
uint8_t* MySigningAtsha204::sha256(const uint8_t* data, size_t sz) {
|
||||
// Initiate SHA256 calculator
|
||||
(void)atsha204.sha204m_execute(SHA204_SHA, SHA_INIT, 0, 0, NULL,
|
||||
SHA_COUNT_SHORT, tx_buffer, SHA_RSP_SIZE_SHORT, rx_buffer);
|
||||
|
||||
// Calculate a hash
|
||||
memset(temp_message, 0x00, SHA_MSG_SIZE);
|
||||
memcpy(temp_message, data, sz);
|
||||
temp_message[sz] = 0x80;
|
||||
// Write length data to the last bytes
|
||||
temp_message[SHA_MSG_SIZE-2] = (sz >> 5);
|
||||
temp_message[SHA_MSG_SIZE-1] = (sz << 3);
|
||||
DEBUG_SIGNING_PRINTBUF(F("DTH:"), temp_message, SHA_MSG_SIZE); // DTH = Data to hash
|
||||
(void)atsha204.sha204m_execute(SHA204_SHA, SHA_CALC, 0, SHA_MSG_SIZE, temp_message,
|
||||
SHA_COUNT_LONG, tx_buffer, SHA_RSP_SIZE_LONG, rx_buffer);
|
||||
|
||||
// Put device back to sleep
|
||||
atsha204.sha204c_sleep();
|
||||
|
||||
DEBUG_SIGNING_PRINTBUF(F("SHA:"), &rx_buffer[SHA204_BUFFER_POS_DATA], 32);
|
||||
return &rx_buffer[SHA204_BUFFER_POS_DATA];
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* ATSHA204 signing backend. The Atmel ATSHA204 offers true random number generation and
|
||||
* HMAC-SHA256 authentication with a readout-protected key.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MySigningAtsha204_h
|
||||
#define MySigningAtsha204_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MySigning.h"
|
||||
#include "utility/ATSHA204.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SIGNING_IDENTIFIER (1)
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
typedef struct {
|
||||
uint8_t nodeId;
|
||||
uint8_t serial[SHA204_SERIAL_SZ];
|
||||
} whitelist_entry_t;
|
||||
#endif
|
||||
|
||||
// The ATSHA204 is capable of generating proper random numbers for nonce
|
||||
// and can calculate HMAC-SHA256 signatures. This is enterprise-
|
||||
// level of security and ought to implement the signing needs for anybody.
|
||||
class MySigningAtsha204 : public MySigning
|
||||
{
|
||||
public:
|
||||
MySigningAtsha204(bool requestSignatures=true,
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t nof_whitelist_entries=0, const whitelist_entry_t* the_whitelist=NULL,
|
||||
#endif
|
||||
uint8_t atshaPin=MY_ATSHA204_PIN);
|
||||
bool getNonce(MyMessage &msg);
|
||||
bool checkTimer(void);
|
||||
bool putNonce(MyMessage &msg);
|
||||
bool signMsg(MyMessage &msg);
|
||||
bool verifyMsg(MyMessage &msg);
|
||||
private:
|
||||
ATSHA204Class atsha204;
|
||||
unsigned long timestamp;
|
||||
bool verification_ongoing;
|
||||
uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH+SHA204_SERIAL_SZ+1];
|
||||
uint8_t temp_message[SHA_MSG_SIZE];
|
||||
uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
|
||||
uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
|
||||
void calculateSignature(MyMessage &msg);
|
||||
uint8_t* sha256(const uint8_t* data, size_t sz);
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t whitlist_sz;
|
||||
const whitelist_entry_t* whitelist;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,283 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* ATSHA204 emulated signing backend. The emulated ATSHA204 implementation offers pseudo random
|
||||
* number generation and HMAC-SHA256 authentication compatible with a "physical" ATSHA204.
|
||||
* NOTE: Key is stored in clear text in the Arduino firmware. Therefore, the use of this back-end
|
||||
* could compromise the key used in the signed message infrastructure if device is lost and its memory
|
||||
* dumped.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MySigning.h"
|
||||
#include "MySigningAtsha204Soft.h"
|
||||
#include "utility/sha256.h"
|
||||
|
||||
// Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected)
|
||||
//#define DEBUG_SIGNING
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
#define DEBUG_SIGNING_PRINTLN(args) Serial.println(args)
|
||||
#else
|
||||
#define DEBUG_SIGNING_PRINTLN(args)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
int i;
|
||||
Serial.println(str);
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
if (buf[i] < 0x10)
|
||||
{
|
||||
Serial.print('0'); // Because Serial.print does not 0-pad HEX
|
||||
}
|
||||
Serial.print(buf[i], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#else
|
||||
#define DEBUG_SIGNING_PRINTBUF(str, buf, sz)
|
||||
#endif
|
||||
|
||||
MySigningAtsha204Soft::MySigningAtsha204Soft(bool requestSignatures,
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t nof_whitelist_entries, const whitelist_entry_t* the_whitelist,
|
||||
const uint8_t* the_serial,
|
||||
#endif
|
||||
uint8_t randomseedPin)
|
||||
:
|
||||
MySigning(requestSignatures),
|
||||
rndPin(randomseedPin),
|
||||
hmacKey({MY_HMAC_KEY}),
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
whitlist_sz(nof_whitelist_entries),
|
||||
whitelist(the_whitelist),
|
||||
node_serial_info(the_serial),
|
||||
#endif
|
||||
verification_ongoing(false),
|
||||
Sha256()
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
bool MySigningAtsha204Soft::getNonce(MyMessage &msg) {
|
||||
// Set randomseed
|
||||
randomSeed(analogRead(rndPin));
|
||||
|
||||
// We used a basic whitening technique that takes the first byte of a new random value and builds up a 32-byte random value
|
||||
// This 32-byte random value is then hashed (SHA256) to produce the resulting nonce
|
||||
Sha256.init();
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Sha256.write(random(255));
|
||||
}
|
||||
memcpy(current_nonce, Sha256.result(), MAX_PAYLOAD);
|
||||
|
||||
// We set the part of the 32-byte nonce that does not fit into a message to 0xAA
|
||||
memset(¤t_nonce[MAX_PAYLOAD], 0xAA, sizeof(current_nonce)-MAX_PAYLOAD);
|
||||
|
||||
// Replace the first byte in the nonce with our signing identifier
|
||||
current_nonce[0] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Transfer the first part of the nonce to the message
|
||||
msg.set(current_nonce, MAX_PAYLOAD);
|
||||
verification_ongoing = true;
|
||||
timestamp = millis(); // Set timestamp to determine when to purge nonce
|
||||
// Be a little fancy to handle turnover (prolong the time allowed to timeout after turnover)
|
||||
// Note that if message is "too" quick, and arrives before turnover, it will be rejected
|
||||
// but this is consider such a rare case that it is accepted and rejects are 'safe'
|
||||
if (timestamp + MY_VERIFICATION_TIMEOUT_MS < millis()) timestamp = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204Soft::checkTimer() {
|
||||
if (verification_ongoing) {
|
||||
if (millis() < timestamp || millis() > timestamp + MY_VERIFICATION_TIMEOUT_MS) {
|
||||
DEBUG_SIGNING_PRINTLN(F("VT")); // VT = Verification timeout
|
||||
// Purge nonce
|
||||
memset(current_nonce, 0xAA, 32);
|
||||
verification_ongoing = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204Soft::putNonce(MyMessage &msg) {
|
||||
if (((uint8_t*)msg.getCustom())[0] != SIGNING_IDENTIFIER) {
|
||||
DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(current_nonce, (uint8_t*)msg.getCustom(), MAX_PAYLOAD);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204Soft::signMsg(MyMessage &msg) {
|
||||
// If we cannot fit any signature in the message, refuse to sign it
|
||||
if (mGetLength(msg) > MAX_PAYLOAD-2) {
|
||||
DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate signature of message
|
||||
mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
|
||||
calculateSignature(msg);
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
// Salt the signature with the senders nodeId and the (hopefully) unique serial The Creator has provided
|
||||
Sha256.init();
|
||||
for (int i=0; i<32; i++) Sha256.write(hmac[i]);
|
||||
Sha256.write(msg.sender);
|
||||
for (int i=0; i<SHA204_SERIAL_SZ; i++) Sha256.write(node_serial_info[i]);
|
||||
memcpy(hmac, Sha256.result(), 32);
|
||||
DEBUG_SIGNING_PRINTLN(F("SWS")); // SWS = Signature whitelist salted
|
||||
#endif
|
||||
|
||||
// Overwrite the first byte in the signature with the signing identifier
|
||||
hmac[0] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Transfer as much signature data as the remaining space in the message permits
|
||||
memcpy(&msg.data[mGetLength(msg)], hmac, MAX_PAYLOAD-mGetLength(msg));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningAtsha204Soft::verifyMsg(MyMessage &msg) {
|
||||
if (!verification_ongoing) {
|
||||
DEBUG_SIGNING_PRINTLN(F("NAVS")); // NAVS = No active verification session
|
||||
return false;
|
||||
} else {
|
||||
// Make sure we have not expired
|
||||
if (!checkTimer()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
verification_ongoing = false;
|
||||
|
||||
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER) {
|
||||
DEBUG_SIGNING_PRINTLN(F("ISI")); // ISI = Incorrect signing identifier
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get signature of message
|
||||
DEBUG_SIGNING_PRINTBUF(F("SIM:"), (uint8_t*)&msg.data[mGetLength(msg)], MAX_PAYLOAD-mGetLength(msg)); // SIM = Signature in message
|
||||
calculateSignature(msg);
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
// Look up the senders nodeId in our whitelist and salt the signature with that data
|
||||
for (int j=0; j < whitlist_sz; j++) {
|
||||
if (whitelist[j].nodeId == msg.sender) {
|
||||
DEBUG_SIGNING_PRINTLN(F("SIW")); // SIW = Sender found in whitelist
|
||||
Sha256.init();
|
||||
for (int i=0; i<32; i++) Sha256.write(hmac[i]);
|
||||
Sha256.write(msg.sender);
|
||||
for (int i=0; i<SHA204_SERIAL_SZ; i++) Sha256.write(whitelist[j].serial[i]);
|
||||
memcpy(hmac, Sha256.result(), 32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Overwrite the first byte in the signature with the signing identifier
|
||||
hmac[0] = SIGNING_IDENTIFIER;
|
||||
|
||||
// Compare the caluclated signature with the provided signature
|
||||
if (memcmp(&msg.data[mGetLength(msg)], hmac, MAX_PAYLOAD-mGetLength(msg))) {
|
||||
DEBUG_SIGNING_PRINTBUF(F("SNOK:"), hmac, MAX_PAYLOAD-mGetLength(msg)); // SNOK = Signature bad
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
DEBUG_SIGNING_PRINTLN(F("W?")); // W? = Is the sender whitelisted?
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
DEBUG_SIGNING_PRINTLN(F("SOK")); // SOK = Signature OK
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to calculate signature of msg (returned in hmac)
|
||||
void MySigningAtsha204Soft::calculateSignature(MyMessage &msg) {
|
||||
memset(temp_message, 0, 32);
|
||||
memcpy(temp_message, (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg)));
|
||||
DEBUG_SIGNING_PRINTBUF(F("MSG:"), (uint8_t*)&msg.data[1-HEADER_SIZE], MAX_MESSAGE_LENGTH-1-(MAX_PAYLOAD-mGetLength(msg))); // MSG = Message to sign
|
||||
DEBUG_SIGNING_PRINTBUF(F("CNC:"), current_nonce, 32); // CNC = Current nonce
|
||||
|
||||
// ATSHA204 calculates the HMAC with a PSK and a SHA256 digest of the following data:
|
||||
// 32 bytes zeroes
|
||||
// 32 bytes digest,
|
||||
// 1 byte OPCODE (0x11)
|
||||
// 1 byte Mode (0x04)
|
||||
// 2 bytes SlotID (0x0000)
|
||||
// 11 bytes zeroes
|
||||
// SN[8] (0xEE)
|
||||
// 4 bytes zeroes
|
||||
// SN[0:1] (0x0123)
|
||||
// 2 bytes zeroes
|
||||
|
||||
// The digest is calculated as a SHA256 digest of the following:
|
||||
// 32 bytes message
|
||||
// 1 byte OPCODE (0x15)
|
||||
// 1 byte param1 (0x02)
|
||||
// 2 bytes param2 (0x0800)
|
||||
// SN[8] (0xEE)
|
||||
// SN[0:1] (0x0123)
|
||||
// 25 bytes zeroes
|
||||
// 32 bytes nonce
|
||||
|
||||
// Calculate message digest first
|
||||
Sha256.init();
|
||||
for (int i=0; i<32; i++) Sha256.write(temp_message[i]);
|
||||
Sha256.write(0x15); // OPCODE
|
||||
Sha256.write(0x02); // param1
|
||||
Sha256.write(0x08); // param2(1)
|
||||
Sha256.write(0x00); // param2(2)
|
||||
Sha256.write(0xEE); // SN[8]
|
||||
Sha256.write(0x01); // SN[0]
|
||||
Sha256.write(0x23); // SN[1]
|
||||
for (int i=0; i<25; i++) Sha256.write(0x00);
|
||||
for (int i=0; i<32; i++) Sha256.write(current_nonce[i]);
|
||||
// Purge nonce when used
|
||||
memset(current_nonce, 0xAA, 32);
|
||||
memcpy(temp_message, Sha256.result(), 32);
|
||||
|
||||
// Feed "message" to HMAC calculator
|
||||
Sha256.initHmac(hmacKey,32); // Set the key to use
|
||||
for (int i=0; i<32; i++) Sha256.write(0x00); // 32 bytes zeroes
|
||||
for (int i=0; i<32; i++) Sha256.write(temp_message[i]); // 32 bytes digest
|
||||
Sha256.write(0x11); // OPCODE
|
||||
Sha256.write(0x04); // Mode
|
||||
Sha256.write(0x00); // SlotID(1)
|
||||
Sha256.write(0x00); // SlotID(2)
|
||||
for (int i=0; i<11; i++) Sha256.write(0x00); // 11 bytes zeroes
|
||||
Sha256.write(0xEE); // SN[8]
|
||||
for (int i=0; i<4; i++) Sha256.write(0x00); // 4 bytes zeroes
|
||||
Sha256.write(0x01); // SN[0]
|
||||
Sha256.write(0x23); // SN[1]
|
||||
for (int i=0; i<2; i++) Sha256.write(0x00); // 2 bytes zeroes
|
||||
|
||||
memcpy(hmac, Sha256.resultHmac(), 32);
|
||||
|
||||
DEBUG_SIGNING_PRINTBUF(F("HMAC:"), hmac, 32);
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* ATSHA204 emulated signing backend. The emulated ATSHA204 implementation offers pseudo random
|
||||
* number generation and HMAC-SHA256 authentication compatible with a "physical" ATSHA204.
|
||||
* NOTE: Key is stored in clear text in the Arduino firmware. Therefore, the use of this back-end
|
||||
* could compromise the key used in the signed message infrastructure if device is lost and its memory
|
||||
* dumped.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MySigningHmac256Soft_h
|
||||
#define MySigningHmac256Soft_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MySigning.h"
|
||||
#include "utility/ATSHA204.h"
|
||||
#include "utility/sha256.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SIGNING_IDENTIFIER (1)
|
||||
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
typedef struct {
|
||||
uint8_t nodeId;
|
||||
uint8_t serial[SHA204_SERIAL_SZ];
|
||||
} whitelist_entry_t;
|
||||
#endif
|
||||
|
||||
// This implementation is the pure software variant of the ATSHA204.
|
||||
// It is designed to work fully compliant with nodes using ATSHA204 in the network
|
||||
// and therefore uses the same signing identifier as ATSHA204.
|
||||
// Because it is completly software based, the quality of the generated random numbers
|
||||
// is weaker though. Random numbers are generated using the Arduino library and seed
|
||||
// is sampled from an analog pin. This pin should unconnected in the hardware.
|
||||
// The pin is selected using MY_RANDOMSEED_PIN in MyConfig.h.
|
||||
class MySigningAtsha204Soft : public MySigning
|
||||
{
|
||||
public:
|
||||
MySigningAtsha204Soft(bool requestSignatures=true,
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t nof_whitelist_entries=0, const whitelist_entry_t* the_whitelist=NULL,
|
||||
const uint8_t* the_serial=NULL, //SHA204_SERIAL_SZ sized buffer expected if provided
|
||||
#endif
|
||||
uint8_t randomseedPin=MY_RANDOMSEED_PIN);
|
||||
bool getNonce(MyMessage &msg);
|
||||
bool checkTimer(void);
|
||||
bool putNonce(MyMessage &msg);
|
||||
bool signMsg(MyMessage &msg);
|
||||
bool verifyMsg(MyMessage &msg);
|
||||
private:
|
||||
Sha256Class Sha256;
|
||||
unsigned long timestamp;
|
||||
bool verification_ongoing;
|
||||
uint8_t current_nonce[NONCE_NUMIN_SIZE_PASSTHROUGH];
|
||||
uint8_t temp_message[32];
|
||||
uint8_t hmacKey[32];
|
||||
uint8_t rndPin;
|
||||
uint8_t hmac[32];
|
||||
void calculateSignature(MyMessage &msg);
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
uint8_t whitlist_sz;
|
||||
const whitelist_entry_t* whitelist;
|
||||
const uint8_t* node_serial_info;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* Disabled signing backend. Does not provide any security measures.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MySigning.h"
|
||||
#include "MySigningNone.h"
|
||||
|
||||
// Uncomment this to get some useful serial debug info (Serial.print and Serial.println expected)
|
||||
//#define DEBUG_SIGNING
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
#define DEBUG_SIGNING_PRINTLN(args) Serial.println(args)
|
||||
#else
|
||||
#define DEBUG_SIGNING_PRINTLN(args)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_SIGNING
|
||||
static void DEBUG_NONE_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz)
|
||||
{
|
||||
int i;
|
||||
Serial.println(str);
|
||||
for (int i=0; i<sz; i++)
|
||||
{
|
||||
if (buf[i] < 0x10)
|
||||
{
|
||||
Serial.print('0'); // Because Serial.print does not 0-pad HEX
|
||||
}
|
||||
Serial.print(buf[i], HEX);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#else
|
||||
#define DEBUG_NONE_PRINTBUF(str, buf, sz)
|
||||
#endif
|
||||
|
||||
MySigningNone::MySigningNone() : MySigning() {
|
||||
}
|
||||
|
||||
bool MySigningNone::getNonce(MyMessage &msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningNone::checkTimer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningNone::putNonce(MyMessage &msg) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningNone::signMsg(MyMessage &msg) {
|
||||
// If we cannot fit any signature in the message, refuse to sign it
|
||||
if (mGetLength(msg) > MAX_PAYLOAD-2) {
|
||||
DEBUG_SIGNING_PRINTLN(F("MTOL")); // Message too large for signature to fit
|
||||
return false;
|
||||
}
|
||||
mSetSigned(msg, 1); // make sure signing flag is set before signature is calculated
|
||||
msg.data[mGetLength(msg)] = SIGNING_IDENTIFIER; // Add signing identifier
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MySigningNone::verifyMsg(MyMessage &msg) {
|
||||
if (msg.data[mGetLength(msg)] != SIGNING_IDENTIFIER)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Signing support created by Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
* Disabled signing backend. Does not provide any security measures.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef MySigningNone_h
|
||||
#define MySigningNone_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MySigning.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define SIGNING_IDENTIFIER (0)
|
||||
|
||||
// The "none" signing driver that can be used for nodes
|
||||
// not requiring signing
|
||||
// It does check SIGNING_IDENTIFIER byte to avoid illegal mixing of signing back-ends in
|
||||
// the network (as seen by this node) and it does verify proper execution order on the API.
|
||||
// The "none" driver rejects all other back-ends.
|
||||
class MySigningNone : public MySigning
|
||||
{
|
||||
public:
|
||||
MySigningNone();
|
||||
bool getNonce(MyMessage &msg);
|
||||
bool checkTimer(void);
|
||||
bool putNonce(MyMessage &msg);
|
||||
bool signMsg(MyMessage &msg);
|
||||
bool verifyMsg(MyMessage &msg);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyTransport.h"
|
||||
|
||||
MyTransport::MyTransport() {
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyTransport_h
|
||||
#define MyTransport_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define AUTO 0xFF // 0-254. Id 255 is reserved for auto initialization of nodeId.
|
||||
#define NODE_SENSOR_ID 0xFF // Node child id is always created for when a node
|
||||
|
||||
// This is the nodeId for sensor net gateway receiver sketch (where all sensors should send their data).
|
||||
#define GATEWAY_ADDRESS ((uint8_t)0)
|
||||
#define BROADCAST_ADDRESS ((uint8_t)0xFF)
|
||||
|
||||
class MyTransport
|
||||
{
|
||||
public:
|
||||
// MyTransport constructor
|
||||
// different parameters would be needed depending on radio module (e.g. pins connected etc.)
|
||||
// keeping these parameters as #define's in MyConfig to streamline the driver interface
|
||||
MyTransport();
|
||||
// init()
|
||||
// different parameters would be needed depending on radio module (e.g. channel, power, crc, etc.)
|
||||
// keeping these parameters as #define's in MyConfig to streamline the driver interface
|
||||
virtual bool init() = 0;
|
||||
// setAddress(address)
|
||||
// set the node address and start listening to that address (and the broadcast address)
|
||||
virtual void setAddress(uint8_t address) = 0;
|
||||
// getAddress()
|
||||
// returns the current address from the radio driver
|
||||
virtual uint8_t getAddress() = 0;
|
||||
// send(to, data, len)
|
||||
// reliable transmission of the data with given length (in bytes) to the destination address
|
||||
// returns true if successfully submitted
|
||||
virtual bool send(uint8_t to, const void* data, uint8_t len) = 0;
|
||||
// available(to)
|
||||
// returns true if a new packet arrived in the rx buffer
|
||||
// populates "to" parameter with the address the packet was sent to (either own address or broadcast)
|
||||
virtual bool available(uint8_t *to) = 0;
|
||||
// receive(data)
|
||||
// returns length of received packet
|
||||
// populates "data" parameter with received data
|
||||
virtual uint8_t receive(void* data) = 0;
|
||||
// powers down the radio
|
||||
virtual void powerDown() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyTransport.h"
|
||||
#include "MyTransportNRF24.h"
|
||||
|
||||
MyTransportNRF24::MyTransportNRF24(uint8_t ce, uint8_t cs, uint8_t paLevel)
|
||||
:
|
||||
MyTransport(),
|
||||
rf24(ce, cs),
|
||||
_paLevel(paLevel)
|
||||
{
|
||||
}
|
||||
|
||||
bool MyTransportNRF24::init() {
|
||||
// Start up the radio library
|
||||
rf24.begin();
|
||||
|
||||
if (!rf24.isPVariant()) {
|
||||
return false;
|
||||
}
|
||||
rf24.setAutoAck(1);
|
||||
rf24.setAutoAck(BROADCAST_PIPE,false); // Turn off auto ack for broadcast
|
||||
rf24.enableAckPayload();
|
||||
rf24.setChannel(RF24_CHANNEL);
|
||||
rf24.setPALevel(_paLevel);
|
||||
rf24.setDataRate(RF24_DATARATE);
|
||||
rf24.setRetries(5,15);
|
||||
rf24.setCRCLength(RF24_CRC_16);
|
||||
rf24.enableDynamicPayloads();
|
||||
|
||||
// All nodes listen to broadcast pipe (for FIND_PARENT_RESPONSE messages)
|
||||
rf24.openReadingPipe(BROADCAST_PIPE, TO_ADDR(BROADCAST_ADDRESS));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MyTransportNRF24::setAddress(uint8_t address) {
|
||||
_address = address;
|
||||
rf24.openReadingPipe(WRITE_PIPE, TO_ADDR(address));
|
||||
rf24.openReadingPipe(CURRENT_NODE_PIPE, TO_ADDR(address));
|
||||
rf24.startListening();
|
||||
}
|
||||
|
||||
uint8_t MyTransportNRF24::getAddress() {
|
||||
return _address;
|
||||
}
|
||||
|
||||
bool MyTransportNRF24::send(uint8_t to, const void* data, uint8_t len) {
|
||||
// Make sure radio has powered up
|
||||
rf24.powerUp();
|
||||
rf24.stopListening();
|
||||
rf24.openWritingPipe(TO_ADDR(to));
|
||||
bool ok = rf24.write(data, len, to == BROADCAST_ADDRESS);
|
||||
rf24.startListening();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool MyTransportNRF24::available(uint8_t *to) {
|
||||
uint8_t pipe = 255;
|
||||
boolean avail = rf24.available(&pipe);
|
||||
if (pipe == CURRENT_NODE_PIPE)
|
||||
*to = _address;
|
||||
else if (pipe == BROADCAST_PIPE)
|
||||
*to = BROADCAST_ADDRESS;
|
||||
return (rf24.available() && pipe < 6);
|
||||
}
|
||||
|
||||
uint8_t MyTransportNRF24::receive(void* data) {
|
||||
uint8_t len = rf24.getDynamicPayloadSize();
|
||||
rf24.read(data, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
void MyTransportNRF24::powerDown() {
|
||||
rf24.powerDown();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyTransportNRF24_h
|
||||
#define MyTransportNRF24_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MyTransport.h"
|
||||
#include <stdint.h>
|
||||
#include "utility/RF24.h"
|
||||
#include "utility/RF24_config.h"
|
||||
|
||||
#define TO_ADDR(x) (RF24_BASE_RADIO_ID + x)
|
||||
|
||||
#define WRITE_PIPE ((uint8_t)0)
|
||||
#define CURRENT_NODE_PIPE ((uint8_t)1)
|
||||
#define BROADCAST_PIPE ((uint8_t)2)
|
||||
|
||||
class MyTransportNRF24 : public MyTransport
|
||||
{
|
||||
public:
|
||||
MyTransportNRF24(uint8_t ce=RF24_CE_PIN, uint8_t cs=RF24_CS_PIN, uint8_t paLevel=RF24_PA_LEVEL);
|
||||
bool init();
|
||||
void setAddress(uint8_t address);
|
||||
uint8_t getAddress();
|
||||
bool send(uint8_t to, const void* data, uint8_t len);
|
||||
bool available(uint8_t *to);
|
||||
uint8_t receive(void* data);
|
||||
void powerDown();
|
||||
private:
|
||||
RF24 rf24;
|
||||
uint8_t _address;
|
||||
uint8_t _paLevel;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "MyTransport.h"
|
||||
#include "MyTransportRFM69.h"
|
||||
|
||||
MyTransportRFM69::MyTransportRFM69(uint8_t freqBand, uint8_t networkId, uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum)
|
||||
:
|
||||
MyTransport(),
|
||||
radio(slaveSelectPin, interruptPin, isRFM69HW, interruptNum),
|
||||
_freqBand(freqBand),
|
||||
_networkId(networkId)
|
||||
{
|
||||
}
|
||||
|
||||
bool MyTransportRFM69::init() {
|
||||
// Start up the radio library (_address will be set later by the MySensors library)
|
||||
radio.initialize(_freqBand, _address, _networkId);
|
||||
#ifdef RFM69_ENABLE_ENCRYPTION
|
||||
radio.encrypt(ENCRYPTKEY);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void MyTransportRFM69::setAddress(uint8_t address) {
|
||||
_address = address;
|
||||
radio.setAddress(address);
|
||||
}
|
||||
|
||||
uint8_t MyTransportRFM69::getAddress() {
|
||||
return _address;
|
||||
}
|
||||
|
||||
bool MyTransportRFM69::send(uint8_t to, const void* data, uint8_t len) {
|
||||
return radio.sendWithRetry(to,data,len);
|
||||
}
|
||||
|
||||
bool MyTransportRFM69::available(uint8_t *to) {
|
||||
if (radio.TARGETID == BROADCAST_ADDRESS)
|
||||
*to = BROADCAST_ADDRESS;
|
||||
else
|
||||
*to = _address;
|
||||
return radio.receiveDone();
|
||||
}
|
||||
|
||||
uint8_t MyTransportRFM69::receive(void* data) {
|
||||
memcpy(data,(const void *)radio.DATA, radio.DATALEN);
|
||||
// Send ack back if this message wasn't a broadcast
|
||||
if (radio.TARGETID != RF69_BROADCAST_ADDR)
|
||||
radio.ACKRequested();
|
||||
radio.sendACK();
|
||||
return radio.DATALEN;
|
||||
}
|
||||
|
||||
void MyTransportRFM69::powerDown() {
|
||||
radio.sleep();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef MyTransportRF69_h
|
||||
#define MyTransportRF69_h
|
||||
|
||||
#include "MyConfig.h"
|
||||
#include "MyTransport.h"
|
||||
#include <stdint.h>
|
||||
#include "utility/RFM69.h"
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
class MyTransportRFM69 : public MyTransport
|
||||
{
|
||||
public:
|
||||
MyTransportRFM69(uint8_t freqBand=RFM69_FREQUENCY, uint8_t networkId=RFM69_NETWORKID, uint8_t slaveSelectPin=RF69_SPI_CS, uint8_t interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, uint8_t interruptNum=RF69_IRQ_NUM);
|
||||
bool init();
|
||||
void setAddress(uint8_t address);
|
||||
uint8_t getAddress();
|
||||
bool send(uint8_t to, const void* data, uint8_t len);
|
||||
bool available(uint8_t *to);
|
||||
uint8_t receive(void* data);
|
||||
void powerDown();
|
||||
private:
|
||||
RFM69 radio;
|
||||
uint8_t _address;
|
||||
uint8_t _freqBand;
|
||||
uint8_t _networkId;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,11 @@
|
||||
/***
|
||||
* This file defines the Sensor library version number
|
||||
* Normally, contributors should not modify this directly
|
||||
* as it is manaaged by the MySensors Bot.
|
||||
* as it is managed by the MySensors Bot.
|
||||
*/
|
||||
#ifndef Version_h
|
||||
#define Version_h
|
||||
|
||||
#define LIBRARY_VERSION "1.4.2"
|
||||
#define LIBRARY_VERSION "1.5"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,20 +1,38 @@
|
||||
/*
|
||||
Vera Arduino MQ2
|
||||
|
||||
connect the MQ2 sensor as follows :
|
||||
|
||||
A H A >>> 5V
|
||||
B >>> A0
|
||||
H >>> GND
|
||||
B >>> 10K ohm >>> GND
|
||||
|
||||
Contribution: epierre
|
||||
Based on http://sandboxelectronics.com/?p=165
|
||||
|
||||
License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
|
||||
|
||||
Modified by HEK to work in 1.4
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Connect the MQ2 sensor as follows :
|
||||
*
|
||||
* A H A >>> 5V
|
||||
* B >>> A0
|
||||
* H >>> GND
|
||||
* B >>> 10K ohm >>> GND
|
||||
*
|
||||
* Contribution: epierre
|
||||
* Based on http://sandboxelectronics.com/?p=165
|
||||
* License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
|
||||
* Modified by HEK to work in 1.4
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
@@ -1,10 +1,37 @@
|
||||
// This is an example that demonstrates how to report the battery level for a sensor
|
||||
// Instructions for measuring battery capacity on A0 are available in the follwoing forum
|
||||
// thread: http://forum.micasaverde.com/index.php/topic,20078.0.html
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This is an example that demonstrates how to report the battery level for a sensor
|
||||
* Instructions for measuring battery capacity on A0 are available here:
|
||||
* http://www.mysensors.org/build/battery
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
#define DEBUG 1 // Debug enables Serial.print 1 = Yes 0 = No
|
||||
|
||||
int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point
|
||||
|
||||
MySensor gw;
|
||||
@@ -25,7 +52,9 @@ void loop()
|
||||
{
|
||||
// get the battery Voltage
|
||||
int sensorValue = analogRead(BATTERY_SENSE_PIN);
|
||||
#if DEBUG > 0
|
||||
Serial.println(sensorValue);
|
||||
#endif
|
||||
|
||||
// 1M, 470K divider across battery and using internal ADC ref of 1.1V
|
||||
// Sense point is bypassed with 0.1 uF cap to reduce noise at that point
|
||||
@@ -34,6 +63,7 @@ void loop()
|
||||
float batteryV = sensorValue * 0.003363075;
|
||||
int batteryPcnt = sensorValue / 10;
|
||||
|
||||
#if DEBUG > 0
|
||||
Serial.print("Battery Voltage: ");
|
||||
Serial.print(batteryV);
|
||||
Serial.println(" V");
|
||||
@@ -41,6 +71,7 @@ void loop()
|
||||
Serial.print("Battery percent: ");
|
||||
Serial.print(batteryPcnt);
|
||||
Serial.println(" %");
|
||||
#endif
|
||||
|
||||
if (oldBatteryPcnt != batteryPcnt) {
|
||||
// Power up radio after sleep
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
// Simple binary switch example
|
||||
// Connect button or door/window reed switch between
|
||||
// digitial I/O pin 3 (BUTTON_PIN below) and GND.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Simple binary switch example
|
||||
* Connect button or door/window reed switch between
|
||||
* digitial I/O pin 3 (BUTTON_PIN below) and GND.
|
||||
* http://www.mysensors.org/build/binary
|
||||
*/
|
||||
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,9 +1,34 @@
|
||||
// Interrupt driven binary switch example with dual interrupts
|
||||
// Author: Patrick 'Anticimex' Fallberg
|
||||
// Connect one button or door/window reed switch between
|
||||
// digitial I/O pin 3 (BUTTON_PIN below) and GND and the other
|
||||
// one in similar fashion on digital I/O pin 2.
|
||||
// This example is designed to fit Arduino Nano/Pro Mini
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Interrupt driven binary switch example with dual interrupts
|
||||
* Author: Patrick 'Anticimex' Fallberg
|
||||
* Connect one button or door/window reed switch between
|
||||
* digitial I/O pin 3 (BUTTON_PIN below) and GND and the other
|
||||
* one in similar fashion on digital I/O pin 2.
|
||||
* This example is designed to fit Arduino Nano/Pro Mini
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,17 +1,41 @@
|
||||
/*
|
||||
*
|
||||
* This sketch clears radioId, relayId and routing info in EEPROM
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This sketch clears radioId, relayId and other routing information in EEPROM back to factory default
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <EEPROM.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(BAUD_RATE);
|
||||
Serial.println("Started clearing. Please wait...");
|
||||
for (int i=0;i<512;i++) {
|
||||
EEPROM.write(i, 0xff);
|
||||
}
|
||||
Serial.println("Clering done. You're ready to go!");
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
||||
@@ -1,14 +1,41 @@
|
||||
// Example sketch showing how to send in OneWire temperature readings
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Example sketch showing how to send in DS1820B OneWire temperature readings back to the controller
|
||||
* http://www.mysensors.org/build/temp
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
#include <DallasTemperature.h>
|
||||
#include <OneWire.h>
|
||||
|
||||
#define COMPARE_TEMP 1 // Send temperature only if changed? 1 = Yes 0 = No
|
||||
|
||||
#define ONE_WIRE_BUS 3 // Pin where dallase sensor is connected
|
||||
#define MAX_ATTACHED_DS18B20 16
|
||||
unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
|
||||
OneWire oneWire(ONE_WIRE_BUS);
|
||||
DallasTemperature sensors(&oneWire);
|
||||
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
|
||||
DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
|
||||
MySensor gw;
|
||||
float lastTemperature[MAX_ATTACHED_DS18B20];
|
||||
int numSensors=0;
|
||||
@@ -19,16 +46,16 @@ MyMessage msg(0,V_TEMP);
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Startup OneWire
|
||||
// Startup up the OneWire library
|
||||
sensors.begin();
|
||||
// requestTemperatures() will not block current thread
|
||||
sensors.setWaitForConversion(false);
|
||||
|
||||
// Startup and initialize MySensors library. Set callback for incoming messages.
|
||||
gw.begin();
|
||||
gw.begin();
|
||||
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Temperature Sensor", "1.0");
|
||||
gw.sendSketchInfo("Temperature Sensor", "1.1");
|
||||
|
||||
// Fetch the number of attached temperature sensors
|
||||
numSensors = sensors.getDeviceCount();
|
||||
@@ -60,10 +87,15 @@ void loop()
|
||||
float temperature = static_cast<float>(static_cast<int>((gw.getConfig().isMetric?sensors.getTempCByIndex(i):sensors.getTempFByIndex(i)) * 10.)) / 10.;
|
||||
|
||||
// Only send data if temperature has changed and no error
|
||||
if (lastTemperature[i] != temperature && temperature != -127.00) {
|
||||
#if COMPARE_TEMP == 1
|
||||
if (lastTemperature[i] != temperature && temperature != -127.00 && temperature != 85.00) {
|
||||
#else
|
||||
if (temperature != -127.00 && temperature != 85.00) {
|
||||
#endif
|
||||
|
||||
// Send in the new temperature
|
||||
gw.send(msg.setSensor(i).set(temperature,1));
|
||||
// Save new temperatures for next compare
|
||||
lastTemperature[i]=temperature;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,27 @@
|
||||
/***
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - February 15, 2014 - Bruce Lacey
|
||||
* Version 1.1 - August 13, 2014 - Converted to 1.4 (hek)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad
|
||||
* <henrik.ekblad@gmail.com> Vera Arduino Sensor project.
|
||||
@@ -13,12 +32,9 @@
|
||||
* to the LED negative terminal and the MOSFET Source pin is connected to ground.
|
||||
*
|
||||
* This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit.
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - February 15, 2014 - Bruce Lacey
|
||||
* Version 1.1 - August 13, 2014 - Converted to 1.4 (hek)
|
||||
*
|
||||
***/
|
||||
* http://www.mysensors.org/build/dimmer
|
||||
*/
|
||||
|
||||
#define SN "DimmableLED"
|
||||
#define SV "1.1"
|
||||
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
/***
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - January 30, 2015 - Developed by GizMoCuz (Domoticz)
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch provides an example how to implement a Dimmable Light
|
||||
@@ -9,12 +27,7 @@
|
||||
* It can be used as a base sketch for actual hardware.
|
||||
* Stores the last light state and level in eeprom.
|
||||
*
|
||||
* Developed by GizMoCuz (Domoticz)
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - January 30, 2015
|
||||
*
|
||||
***/
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch provides an example how to implement a distance sensor using HC-SR04
|
||||
* http://www.mysensors.org/build/distance
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
#include <NewPing.h>
|
||||
|
||||
@@ -1,21 +1,42 @@
|
||||
/*
|
||||
Arduino Dust Sensort
|
||||
|
||||
connect the sensor as follows :
|
||||
|
||||
VCC >>> 5V
|
||||
A >>> A0
|
||||
GND >>> GND
|
||||
|
||||
Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU
|
||||
Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex)
|
||||
Contribution: epierre
|
||||
COnverted to 1.4 by Henrik Ekblad
|
||||
|
||||
The dust sensor used (see purchase guide for latest link):
|
||||
http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=171259125886&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg
|
||||
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - epierre
|
||||
* Converted to 1.4 by Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Arduino Dust Sensort
|
||||
*
|
||||
* connect the sensor as follows :
|
||||
*
|
||||
* VCC >>> 5V
|
||||
* A >>> A0
|
||||
* GND >>> GND
|
||||
*
|
||||
* Based on: http://www.dfrobot.com/wiki/index.php/Sharp_GP2Y1010AU
|
||||
* Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex)
|
||||
*
|
||||
* http://www.mysensors.org/build/dust
|
||||
*
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,11 +1,38 @@
|
||||
// Use this sensor to measure KWH and Watt of your house meeter
|
||||
// You need to set the correct pulsefactor of your meeter (blinks per KWH).
|
||||
// The sensor starts by fetching current KWH value from gateway.
|
||||
// Reports both KWH and Watt back to gateway.
|
||||
//
|
||||
// Unfortunately millis() won't increment when the Arduino is in
|
||||
// sleepmode. So we cannot make this sensor sleep if we also want
|
||||
// to calculate/report watt-number.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch provides an example how to implement a distance sensor using HC-SR04
|
||||
* Use this sensor to measure KWH and Watt of your house meeter
|
||||
* You need to set the correct pulsefactor of your meeter (blinks per KWH).
|
||||
* The sensor starts by fetching current KWH value from gateway.
|
||||
* Reports both KWH and Watt back to gateway.
|
||||
*
|
||||
* Unfortunately millis() won't increment when the Arduino is in
|
||||
* sleepmode. So we cannot make this sensor sleep if we also want
|
||||
* to calculate/report watt-number.
|
||||
* http://www.mysensors.org/build/pulse_power
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
@@ -1,12 +1,28 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
*
|
||||
* Contribution by a-lurker
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
* Contribution by a-lurker and Anticimex,
|
||||
* Contribution by Norbert Truchsess <norbert.truchsess@t-online.de>
|
||||
*
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The EthernetGateway sends data received from sensors to the ethernet link.
|
||||
@@ -16,7 +32,7 @@
|
||||
*
|
||||
*
|
||||
* COMPILING WIZNET (W5100) ETHERNET MODULE
|
||||
* > Edit RF24_config.h in (libraries\MySensors\utility) to enable softspi (remove // before "#define SOFTSPI").
|
||||
* > Edit MyConfig.h in (libraries\MySensors\) to enable softspi (remove // before "#define SOFTSPI").
|
||||
*
|
||||
* COMPILING ENC28J60 ETHERNET MODULE
|
||||
* > Use Arduino IDE 1.5.7 (or later)
|
||||
@@ -30,6 +46,7 @@
|
||||
* E.g. If you want to use the defualt values in this sketch enter: 192.168.178.66:5003
|
||||
*
|
||||
* LED purposes:
|
||||
* - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
||||
* - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
|
||||
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
|
||||
* - ERR (red) - fast blink on error during transmission error or recieve crc error
|
||||
@@ -37,17 +54,29 @@
|
||||
* See http://www.mysensors.org/build/ethernet_gateway for wiring instructions.
|
||||
*
|
||||
*/
|
||||
#define NO_PORTB_PINCHANGES
|
||||
|
||||
#include <DigitalIO.h> // This include can be removed when using UIPEthernet module
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
#include <MyGateway.h>
|
||||
|
||||
#include <MySigningNone.h>
|
||||
#include <MyTransportRFM69.h>
|
||||
#include <MyTransportNRF24.h>
|
||||
#include <MyHwATMega328.h>
|
||||
#include <MySigningAtsha204Soft.h>
|
||||
#include <MySigningAtsha204.h>
|
||||
|
||||
#include <MyParserSerial.h>
|
||||
#include <MySensor.h>
|
||||
#include <stdarg.h>
|
||||
#include <PinChangeInt.h>
|
||||
#include "GatewayUtil.h"
|
||||
|
||||
|
||||
// Use this if you have attached a Ethernet ENC28J60 shields
|
||||
//#include <UIPEthernet.h>
|
||||
// #include <UIPEthernet.h>
|
||||
|
||||
// Use this fo WizNET W5100 module and Arduino Ethernet Shield
|
||||
// Use this for WizNET W5100 module and Arduino Ethernet Shield
|
||||
#include <Ethernet.h>
|
||||
|
||||
|
||||
@@ -56,10 +85,33 @@
|
||||
|
||||
#define RADIO_CE_PIN 5 // radio chip enable
|
||||
#define RADIO_SPI_SS_PIN 6 // radio SPI serial select
|
||||
|
||||
#define RADIO_ERROR_LED_PIN 7 // Error led pin
|
||||
#define RADIO_RX_LED_PIN 8 // Receive led pin
|
||||
#define RADIO_TX_LED_PIN 9 // the PCB, on board LED
|
||||
|
||||
|
||||
// NRFRF24L01 radio driver (set low transmit power by default)
|
||||
MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
||||
//MyTransportRFM69 transport;
|
||||
|
||||
// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
//MySigningNone signer;
|
||||
//MySigningAtsha204Soft signer;
|
||||
//MySigningAtsha204 signer;
|
||||
|
||||
// Hardware profile
|
||||
MyHwATMega328 hw;
|
||||
|
||||
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||
#else
|
||||
MySensor gw(transport, hw /*, signer*/);
|
||||
#endif
|
||||
|
||||
|
||||
#define IP_PORT 5003 // The port you want to open
|
||||
IPAddress myIp (192, 168, 178, 66); // Configure your static ip-address here COMPILE ERROR HERE? Use Arduino IDE 1.5.7 or later!
|
||||
|
||||
@@ -70,75 +122,95 @@ byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // DEAD BEEF FEED
|
||||
|
||||
// a R/W server on the port
|
||||
EthernetServer server = EthernetServer(IP_PORT);
|
||||
|
||||
// No blink or button functionality. Use the vanilla constructor.
|
||||
MyGateway gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, INCLUSION_MODE_TIME);
|
||||
|
||||
// Uncomment this constructor if you have leds and include button attached to your gateway
|
||||
//MyGateway gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN, INCLUSION_MODE_TIME, INCLUSION_MODE_PIN, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||
|
||||
// handle to open connection
|
||||
EthernetClient client = EthernetClient();
|
||||
|
||||
char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface
|
||||
int inputPos = 0;
|
||||
bool sentReady = false;
|
||||
|
||||
void output(const char *fmt, ... ) {
|
||||
va_list args;
|
||||
va_start (args, fmt );
|
||||
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
||||
va_end (args);
|
||||
Serial.print(serialBuffer);
|
||||
client.write(serialBuffer);
|
||||
}
|
||||
|
||||
void setup()
|
||||
{
|
||||
Ethernet.begin(mac, myIp);
|
||||
|
||||
setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output);
|
||||
|
||||
// Add interrupt for inclusion button to pin
|
||||
PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING);
|
||||
|
||||
// give the Ethernet interface a second to initialize
|
||||
delay(1000);
|
||||
|
||||
// Initialize gateway at maximum PA level, channel 70 and callback for write operations
|
||||
gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet);
|
||||
gw.begin(incomingMessage, 0, true, 0);
|
||||
|
||||
|
||||
// start listening for clients
|
||||
server.begin();
|
||||
}
|
||||
|
||||
// This will be called when data should be written to ethernet
|
||||
void writeEthernet(char *writeBuffer) {
|
||||
server.write(writeBuffer);
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
void loop() {
|
||||
gw.process();
|
||||
|
||||
checkButtonTriggeredInclusion();
|
||||
checkInclusionFinished();
|
||||
|
||||
// if an incoming client connects, there will be
|
||||
// bytes available to read via the client object
|
||||
EthernetClient client = server.available();
|
||||
|
||||
if (client) {
|
||||
// if got 1 or more bytes
|
||||
if (client.available()) {
|
||||
// read the bytes incoming from the client
|
||||
char inChar = client.read();
|
||||
|
||||
if (inputPos<MAX_RECEIVE_LENGTH-1) {
|
||||
// if newline then command is complete
|
||||
if (inChar == '\n') {
|
||||
// a command was issued by the client
|
||||
// we will now try to send it to the actuator
|
||||
inputString[inputPos] = 0;
|
||||
|
||||
// echo the string to the serial port
|
||||
Serial.print(inputString);
|
||||
|
||||
gw.parseAndSend(inputString);
|
||||
|
||||
// clear the string:
|
||||
inputPos = 0;
|
||||
} else {
|
||||
// add it to the inputString:
|
||||
inputString[inputPos] = inChar;
|
||||
inputPos++;
|
||||
}
|
||||
} else {
|
||||
// Incoming message too long. Throw away
|
||||
inputPos = 0;
|
||||
}
|
||||
EthernetClient newclient = server.available();
|
||||
// if a new client connects make sure to dispose any previous existing sockets
|
||||
if (newclient) {
|
||||
if (client != newclient) {
|
||||
client.stop();
|
||||
client = newclient;
|
||||
output(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
||||
}
|
||||
}
|
||||
|
||||
if (client) {
|
||||
if (!client.connected()) {
|
||||
client.stop();
|
||||
} else if (client.available()) {
|
||||
// read the bytes incoming from the client
|
||||
char inChar = client.read();
|
||||
if (inputPos<MAX_RECEIVE_LENGTH-1) {
|
||||
// if newline then command is complete
|
||||
if (inChar == '\n') {
|
||||
Serial.println("Finished");
|
||||
// a command was issued by the client
|
||||
// we will now try to send it to the actuator
|
||||
inputString[inputPos] = 0;
|
||||
|
||||
// echo the string to the serial port
|
||||
Serial.print(inputString);
|
||||
|
||||
parseAndSend(gw, inputString);
|
||||
|
||||
// clear the string:
|
||||
inputPos = 0;
|
||||
} else {
|
||||
// add it to the inputString:
|
||||
inputString[inputPos] = inChar;
|
||||
inputPos++;
|
||||
}
|
||||
} else {
|
||||
// Incoming message too long. Throw away
|
||||
inputPos = 0;
|
||||
}
|
||||
}
|
||||
gw.processRadioMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
#ifndef __GATEWAYUTIL_H__
|
||||
#define __GATEWAYUTIL_H__
|
||||
|
||||
#include <MyTransport.h>
|
||||
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
|
||||
uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled
|
||||
uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode
|
||||
|
||||
#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller
|
||||
#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller
|
||||
|
||||
volatile boolean buttonTriggeredInclusion;
|
||||
boolean inclusionMode; // Keeps track on inclusion mode
|
||||
void (*serial)(const char *fmt, ... );
|
||||
|
||||
MyParserSerial parser;
|
||||
|
||||
void setInclusionMode(boolean newMode);
|
||||
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera
|
||||
unsigned long inclusionStartTime;
|
||||
|
||||
void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) {
|
||||
inclusionMode = 0;
|
||||
buttonTriggeredInclusion = false;
|
||||
serial = _serial;
|
||||
|
||||
pinInclusion = _inc;
|
||||
inclusionTime = _incTime;
|
||||
|
||||
// Setup digital in that triggers inclusion mode
|
||||
pinMode(pinInclusion, INPUT);
|
||||
digitalWrite(pinInclusion, HIGH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void startInclusionInterrupt() {
|
||||
buttonTriggeredInclusion = true;
|
||||
}
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) {
|
||||
// gw.rxBlink(3);
|
||||
// } else {
|
||||
// gw.rxBlink(1);
|
||||
// }
|
||||
// Pass along the message from sensors to serial line
|
||||
serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void checkButtonTriggeredInclusion() {
|
||||
if (buttonTriggeredInclusion) {
|
||||
// Ok, someone pressed the inclusion button on the gateway
|
||||
// start inclusion mode for 1 munute.
|
||||
#ifdef DEBUG
|
||||
serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
#endif
|
||||
buttonTriggeredInclusion = false;
|
||||
setInclusionMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void checkInclusionFinished() {
|
||||
if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) {
|
||||
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode
|
||||
setInclusionMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
void parseAndSend(MySensor &gw, char *commandBuffer) {
|
||||
boolean ok;
|
||||
MyMessage &msg = gw.getLastMessage();
|
||||
|
||||
if (parser.parse(msg, commandBuffer)) {
|
||||
uint8_t command = mGetCommand(msg);
|
||||
|
||||
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
||||
// Handle messages directed to gateway
|
||||
if (msg.type == I_VERSION) {
|
||||
// Request for version
|
||||
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
||||
} else if (msg.type == I_INCLUSION_MODE) {
|
||||
// Request to change inclusion mode
|
||||
setInclusionMode(atoi(msg.data) == 1);
|
||||
}
|
||||
} else {
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
gw.txBlink(1);
|
||||
#endif
|
||||
ok = gw.sendRoute(msg);
|
||||
if (!ok) {
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
gw.errBlink(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setInclusionMode(boolean newMode) {
|
||||
if (newMode != inclusionMode) {
|
||||
inclusionMode = newMode;
|
||||
// Send back mode change on serial line to ack command
|
||||
serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0);
|
||||
|
||||
if (inclusionMode) {
|
||||
inclusionStartTime = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
#error This example is only for use on Arduino.
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,32 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch provides an example how to implement a humidity/temperature
|
||||
* sensor using DHT11/DHT-22
|
||||
* http://www.mysensors.org/build/humidity
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
#include <DHT.h>
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
// Example sketch showing how to control ir devices
|
||||
// An IR LED must be connected to Arduino PWM pin 3.
|
||||
// An optional ir receiver can be connected to PWM pin 8.
|
||||
// All receied ir signals will be sent to gateway device stored in VAR_1.
|
||||
// When binary light on is clicked - sketch will send volume up ir command
|
||||
// When binary light off is clicked - sketch will send volume down ir command
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to control ir devices
|
||||
* An IR LED must be connected to Arduino PWM pin 3.
|
||||
* An optional ir receiver can be connected to PWM pin 8.
|
||||
* All receied ir signals will be sent to gateway device stored in VAR_1.
|
||||
* When binary light on is clicked - sketch will send volume up ir command
|
||||
* When binary light off is clicked - sketch will send volume down ir command
|
||||
* http://www.mysensors.org/build/ir
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,20 +1,41 @@
|
||||
/*
|
||||
Vera Arduino BH1750FVI Light sensor
|
||||
communicate using I2C Protocol
|
||||
this library enable 2 slave device addresses
|
||||
Main address 0x23
|
||||
secondary address 0x5C
|
||||
connect the sensor as follows :
|
||||
|
||||
VCC >>> 5V
|
||||
Gnd >>> Gnd
|
||||
ADDR >>> NC or GND
|
||||
SCL >>> A5
|
||||
SDA >>> A4
|
||||
|
||||
Contribution: idefix
|
||||
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - idefix
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Arduino BH1750FVI Light sensor
|
||||
* communicate using I2C Protocol
|
||||
* this library enable 2 slave device addresses
|
||||
* Main address 0x23
|
||||
* secondary address 0x5C
|
||||
* connect the sensor as follows :
|
||||
*
|
||||
* VCC >>> 5V
|
||||
* Gnd >>> Gnd
|
||||
* ADDR >>> NC or GND
|
||||
* SCL >>> A5
|
||||
* SDA >>> A4
|
||||
* http://www.mysensors.org/build/light
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik EKblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to measue light level using a LM393 photo-resistor
|
||||
* http://www.mysensors.org/build/light
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
|
||||
+36
-11
@@ -1,14 +1,39 @@
|
||||
// MAX6875 Hight temperature sensor with range: -200 degC - +1300 degC
|
||||
// Contribution by MrLynx
|
||||
// http://forum.mysensors.org/topic/641/max6675
|
||||
//
|
||||
// Connect:
|
||||
// MAX6675 - Arduino
|
||||
// CS0 - 4
|
||||
// SO - 3
|
||||
// SCLK - 5
|
||||
// VCC - 5V
|
||||
// GND - GND
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - MrLynx
|
||||
*
|
||||
* DESCRIPTION
|
||||
* MAX6875 High temperature sensor with range: -200 degC - +1300 degC
|
||||
* http://forum.mysensors.org/topic/641/max6675
|
||||
*
|
||||
* Connect MAX6675 - Arduino
|
||||
* CS0 - 4
|
||||
* SO - 3
|
||||
* SCLK - 5
|
||||
* VCC - 5V
|
||||
* GND - GND
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <MAX6675.h>
|
||||
|
||||
@@ -1,66 +1,97 @@
|
||||
/* MyMQTT Broker Gateway 0.1b
|
||||
|
||||
Created by Daniel Wiegert <daniel.wiegert@gmail.com>
|
||||
Based on MySensors Ethernet Gateway by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
http://www.mysensors.org
|
||||
|
||||
Requires MySensors lib 1.4b
|
||||
|
||||
* Change below; TCP_IP, TCP_PORT, TCP_MAC
|
||||
This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also.
|
||||
*1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges.
|
||||
|
||||
*2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change
|
||||
the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details.
|
||||
http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5
|
||||
|
||||
* Don't forget to look at the definitions in libraries\MySensors\MyMQTT.h!
|
||||
|
||||
define TCPDUMP and connect serial interface if you have problems, please write on
|
||||
http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to
|
||||
turn on DEBUG in libraries\MySensors\MyConfig.h also.
|
||||
|
||||
MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition.
|
||||
If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20.
|
||||
To disable: set MQTT_FIRST_SENSORID to 255.
|
||||
|
||||
MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like.
|
||||
|
||||
MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes.
|
||||
This can be useful if you want to send latest state back to the MQTT client. Just check if incoming
|
||||
message has any length or not.
|
||||
Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things.
|
||||
|
||||
* Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType]
|
||||
NodeID and SensorID is uint8 (0-255) number.
|
||||
Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions.
|
||||
User can change this to their needs. We have also left some space for custom types.
|
||||
|
||||
Special: (sensor 255 reserved for special commands)
|
||||
You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version)
|
||||
|
||||
To-do:
|
||||
Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself.
|
||||
Be able to send ACK so client returns the data being sent.
|
||||
... Please come with ideas!
|
||||
What to do with publish messages.
|
||||
|
||||
Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation)
|
||||
- http://www.openhab.org/
|
||||
- https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en
|
||||
... Please notify me if you use this broker with other software.
|
||||
|
||||
|
||||
* How to set-up Openhab and MQTTGateway:
|
||||
http://forum.mysensors.org/topic/303/mqtt-broker-gateway
|
||||
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Created by Daniel Wiegert <daniel.wiegert@gmail.com>
|
||||
*
|
||||
* DESCRIPTION
|
||||
* MyMQTT Broker Gateway 0.1b
|
||||
* Latest instructions found here:
|
||||
* http://www.mysensors.org/build/mqtt_gateway
|
||||
* http://www.mysensors.org/build/ethernet_gateway
|
||||
*
|
||||
* Change below; TCP_IP, TCP_PORT, TCP_MAC
|
||||
* This will listen on your selected TCP_IP:TCP_PORT below, Please change TCP_MAC your liking also.
|
||||
* 1 -> NOTE: Keep first byte at x2, x6, xA or xE (replace x with any hex value) for using Local Ranges.
|
||||
* 2 You can use standard pin set-up as MySensors recommends or if you own a IBOARD you may change
|
||||
* the radio-pins below if you hardware mod your iBoard. see [URL BELOW] for more details.
|
||||
* http://forum.mysensors.org/topic/224/iboard-cheap-single-board-ethernet-arduino-with-radio/5
|
||||
*
|
||||
* Don't forget to look at the definitions in MyMQTT.h!
|
||||
*
|
||||
* define TCPDUMP and connect serial interface if you have problems, please write on
|
||||
* http://forum.mysensors.org/ and explain your problem, include serial output. Don't forget to
|
||||
* turn on DEBUG in libraries\MySensors\MyConfig.h also.
|
||||
*
|
||||
* MQTT_FIRST_SENSORID is for 'DHCP' server in MyMQTT. You may limit the ID's with FIRST and LAST definition.
|
||||
* If you want your manually configured below 20 set MQTT_FIRST_SENSORID to 20.
|
||||
* To disable: set MQTT_FIRST_SENSORID to 255.
|
||||
*
|
||||
* MQTT_BROKER_PREFIX is the leading prefix for your nodes. This can be only one char if like.
|
||||
*
|
||||
* MQTT_SEND_SUBSCRIPTION is if you want the MyMQTT to send a empty payload message to your nodes.
|
||||
* This can be useful if you want to send latest state back to the MQTT client. Just check if incoming
|
||||
* message has any length or not.
|
||||
* Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things.
|
||||
*
|
||||
* (*) Address-layout is : [MQTT_BROKER_PREFIX]/[NodeID]/[SensorID]/V_[SensorType]
|
||||
* NodeID and SensorID is uint8 (0-255) number.
|
||||
* Last segment is translation of the sensor type, look inside MyMQTT.cpp for the definitions.
|
||||
* User can change this to their needs. We have also left some space for custom types.
|
||||
*
|
||||
* Special: (sensor 255 reserved for special commands)
|
||||
* You can receive a node sketch name with MyMQTT/20/255/V_Sketch_name (or version with _version)
|
||||
*
|
||||
* To-do:
|
||||
* Special commands : clear or set EEPROM Values, Send REBOOT and Receive reboot for MyMQTT itself.
|
||||
* Be able to send ACK so client returns the data being sent.
|
||||
* ... Please come with ideas!
|
||||
* What to do with publish messages.
|
||||
*
|
||||
* Test in more MQTT clients, So far tested in openhab and MyMQTT for Android (Not my creation)
|
||||
* - http://www.openhab.org/
|
||||
* - https://play.google.com/store/apps/details?id=at.tripwire.mqtt.client&hl=en
|
||||
* ... Please notify me if you use this broker with other software.
|
||||
*
|
||||
* How to set-up Openhab and MQTTGateway:
|
||||
* http://forum.mysensors.org/topic/303/mqtt-broker-gateway
|
||||
*/
|
||||
|
||||
#include <DigitalIO.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#include <MySigningNone.h>
|
||||
#include <MyTransportRFM69.h>
|
||||
#include <MyTransportNRF24.h>
|
||||
#include <MyHwATMega328.h>
|
||||
#include <MySigningAtsha204Soft.h>
|
||||
#include <MySigningAtsha204.h>
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <MyMQTT.h>
|
||||
#include <MsTimer2.h>
|
||||
#include <Ethernet.h>
|
||||
#include "MyMQTT.h"
|
||||
|
||||
|
||||
#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
|
||||
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
|
||||
|
||||
// * Use this for IBOARD modded to use standard MISO/MOSI/SCK, see note *1 above!
|
||||
/*
|
||||
@@ -73,6 +104,7 @@ http://forum.mysensors.org/topic/303/mqtt-broker-gateway
|
||||
|
||||
// * Use this for default configured pro mini / nano etc :
|
||||
///*
|
||||
|
||||
#define RADIO_CE_PIN 5 // radio chip enable
|
||||
#define RADIO_SPI_SS_PIN 6 // radio SPI serial select
|
||||
#define RADIO_ERROR_LED_PIN 7 // Error led pin
|
||||
@@ -85,9 +117,44 @@ byte TCP_MAC[] = { 0x02, 0xDE, 0xAD, 0x00, 0x00, 0x42 }; // Mac-address - You sh
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
// NRFRF24L01 radio driver (set low transmit power by default)
|
||||
MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
||||
//MyTransportRFM69 transport;
|
||||
|
||||
// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
//MySigningNone signer;
|
||||
//MySigningAtsha204Soft signer;
|
||||
//MySigningAtsha204 signer;
|
||||
|
||||
// Hardware profile
|
||||
MyHwATMega328 hw;
|
||||
|
||||
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
MySensor gw(transport, hw /*, signer*/);
|
||||
|
||||
|
||||
EthernetServer server = EthernetServer(TCP_PORT);
|
||||
EthernetClient *currentClient = NULL;
|
||||
MyMQTT gw(RADIO_CE_PIN, RADIO_SPI_SS_PIN);
|
||||
MyMessage msg;
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
char broker[] PROGMEM = MQTT_BROKER_PREFIX;
|
||||
bool MQTTClientConnected = false;
|
||||
uint8_t buffsize;
|
||||
char buffer[MQTT_MAX_PACKET_SIZE];
|
||||
volatile uint8_t countRx;
|
||||
volatile uint8_t countTx;
|
||||
volatile uint8_t countErr;
|
||||
|
||||
|
||||
void writeEthernet(const char *writeBuffer, uint8_t *writeSize) {
|
||||
#ifdef TCPDUMP
|
||||
Serial.print(">>");
|
||||
char buf[4];
|
||||
for (uint8_t a=0; a<*writeSize; a++) { sprintf(buf,"%02X ",(uint8_t)writeBuffer[a]); Serial.print(buf); } Serial.println("");
|
||||
#endif
|
||||
server.write((const uint8_t *)writeBuffer, *writeSize);
|
||||
}
|
||||
|
||||
|
||||
void processEthernetMessages() {
|
||||
char inputString[MQTT_MAX_PACKET_SIZE] = "";
|
||||
@@ -120,32 +187,287 @@ void processEthernetMessages() {
|
||||
char buf[4];
|
||||
for (byte a=0; a<inputSize; a++) { sprintf(buf, "%02X ", (byte)inputString[a]); Serial.print(buf); } Serial.println();
|
||||
#endif
|
||||
gw.processMQTTMessage(inputString, inputSize);
|
||||
processMQTTMessage(inputString, inputSize);
|
||||
currentClient = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void writeEthernet(const char *writeBuffer, byte *writeSize) {
|
||||
#ifdef TCPDUMP
|
||||
Serial.print(">>");
|
||||
char buf[4];
|
||||
for (byte a=0; a<*writeSize; a++) { sprintf(buf,"%02X ",(byte)writeBuffer[a]); Serial.print(buf); } Serial.println();
|
||||
#endif
|
||||
// Check whether to respond to a single client or write to all
|
||||
if (currentClient != NULL)
|
||||
currentClient->write((const byte *)writeBuffer, *writeSize);
|
||||
else
|
||||
server.write((const byte *)writeBuffer, *writeSize);
|
||||
|
||||
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
rxBlink(1);
|
||||
sendMQTT(message);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Ethernet.begin(TCP_MAC, TCP_IP);
|
||||
|
||||
|
||||
countRx = 0;
|
||||
countTx = 0;
|
||||
countErr = 0;
|
||||
|
||||
// Setup led pins
|
||||
pinMode(RADIO_RX_LED_PIN, OUTPUT);
|
||||
pinMode(RADIO_TX_LED_PIN, OUTPUT);
|
||||
pinMode(RADIO_ERROR_LED_PIN, OUTPUT);
|
||||
digitalWrite(RADIO_RX_LED_PIN, LOW);
|
||||
digitalWrite(RADIO_TX_LED_PIN, LOW);
|
||||
digitalWrite(RADIO_ERROR_LED_PIN, LOW);
|
||||
|
||||
|
||||
// Set initial state of leds
|
||||
digitalWrite(RADIO_RX_LED_PIN, HIGH);
|
||||
digitalWrite(RADIO_TX_LED_PIN, HIGH);
|
||||
digitalWrite(RADIO_ERROR_LED_PIN, HIGH);
|
||||
|
||||
|
||||
// Add led timer interrupt
|
||||
MsTimer2::set(300, ledTimersInterrupt);
|
||||
MsTimer2::start();
|
||||
|
||||
|
||||
// give the Ethernet interface a second to initialize
|
||||
delay(1000);
|
||||
|
||||
|
||||
// Initialize gateway at maximum PA level, channel 70 and callback for write operations
|
||||
gw.begin(incomingMessage, 0, true, 0);
|
||||
|
||||
// start listening for clients
|
||||
server.begin();
|
||||
|
||||
Serial.println("Ok!");
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
init();
|
||||
Ethernet.begin(TCP_MAC, TCP_IP);
|
||||
delay(1000); // Wait for Ethernet to get configured.
|
||||
gw.begin(RF24_PA_LEVEL_GW, RF24_CHANNEL, RF24_DATARATE, writeEthernet, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||
server.begin();
|
||||
while (1) {
|
||||
processEthernetMessages();
|
||||
gw.processRadioMessage();
|
||||
}
|
||||
void loop()
|
||||
{
|
||||
gw.process();
|
||||
|
||||
processEthernetMessages();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
inline MyMessage& build (MyMessage &msg, uint8_t destination, uint8_t sensor, uint8_t command, uint8_t type, bool enableAck) {
|
||||
msg.destination = destination;
|
||||
msg.sender = GATEWAY_ADDRESS;
|
||||
msg.sensor = sensor;
|
||||
msg.type = type;
|
||||
mSetCommand(msg,command);
|
||||
mSetRequestAck(msg,enableAck);
|
||||
mSetAck(msg,false);
|
||||
return msg;
|
||||
}
|
||||
|
||||
char *getType(char *b, const char **index) {
|
||||
char *q = b;
|
||||
char *p = (char *)pgm_read_word(index);
|
||||
while (*q++ = pgm_read_byte(p++));
|
||||
*q=0;
|
||||
return b;
|
||||
}
|
||||
|
||||
void processMQTTMessage(char *inputString, uint8_t inputPos) {
|
||||
char *str, *p;
|
||||
uint8_t i = 0;
|
||||
buffer[0]= 0;
|
||||
buffsize = 0;
|
||||
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTCONNECT) {
|
||||
buffer[buffsize++] = MQTTCONNACK << 4;
|
||||
buffer[buffsize++] = 0x02; // Remaining length
|
||||
buffer[buffsize++] = 0x00; // Connection accepted
|
||||
buffer[buffsize++] = 0x00; // Reserved
|
||||
MQTTClientConnected=true; // We have connection!
|
||||
}
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTPINGREQ) {
|
||||
buffer[buffsize++] = MQTTPINGRESP << 4;
|
||||
buffer[buffsize++] = 0x00;
|
||||
}
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) {
|
||||
buffer[buffsize++] = MQTTSUBACK << 4; // Just ack everything, we actually dont really care!
|
||||
buffer[buffsize++] = 0x03; // Remaining length
|
||||
buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB
|
||||
buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB
|
||||
buffer[buffsize++] = MQTTQOS0; // QOS level
|
||||
}
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTUNSUBSCRIBE) {
|
||||
buffer[buffsize++] = MQTTUNSUBACK << 4;
|
||||
buffer[buffsize++] = 0x02; // Remaining length
|
||||
buffer[buffsize++] = (uint8_t)inputString[2]; // Message ID MSB
|
||||
buffer[buffsize++] = (uint8_t)inputString[3]; // Message ID LSB
|
||||
}
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTDISCONNECT) {
|
||||
MQTTClientConnected=false; // We lost connection!
|
||||
}
|
||||
if (buffsize > 0) {
|
||||
writeEthernet(buffer,&buffsize);
|
||||
}
|
||||
|
||||
// We publish everything we get, we dont care if its subscribed or not!
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTPUBLISH || (MQTT_SEND_SUBSCRIPTION && (uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) {
|
||||
buffer[0]= 0;
|
||||
buffsize = 0;
|
||||
// Cut out address and payload depending on message type.
|
||||
if ((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE) {
|
||||
strncat(buffer,inputString+6,inputString[5]);
|
||||
} else {
|
||||
strncat(buffer,inputString+4,inputString[3]);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
Serial.println(buffer);
|
||||
#endif
|
||||
// TODO: Check if we should send ack or not.
|
||||
for (str = strtok_r(buffer,"/",&p) ; str && i<4 ; str = strtok_r(NULL,"/",&p)) {
|
||||
if (i == 0) {
|
||||
if (strcmp_P(str,broker)!=0) { //look for MQTT_BROKER_PREFIX
|
||||
return; //Message not for us or malformatted!
|
||||
}
|
||||
} else if (i==1) {
|
||||
msg.destination = atoi(str); //NodeID
|
||||
} else if (i==2) {
|
||||
msg.sensor = atoi(str); //SensorID
|
||||
} else if (i==3) {
|
||||
char match=255; //SensorType
|
||||
#ifdef MQTT_TRANSLATE_TYPES
|
||||
|
||||
for (uint8_t j=0; strcpy_P(convBuf, (char*)pgm_read_word(&(vType[j]))) ; j++) {
|
||||
if (strcmp((char*)&str[2],convBuf)==0) { //Strip V_ and compare
|
||||
match=j;
|
||||
break;
|
||||
}
|
||||
if (j >= V_TOTAL) break;
|
||||
}
|
||||
|
||||
#endif
|
||||
if ( atoi(str)!=0 || str=="0" ) {
|
||||
match=atoi(str);
|
||||
}
|
||||
|
||||
if (match==255) {
|
||||
match=V_UNKNOWN;
|
||||
}
|
||||
msg.type = match;
|
||||
}
|
||||
i++;
|
||||
} //Check if packge has payload
|
||||
if ((uint8_t)inputString[1] > (uint8_t)(inputString[3]+2) && !((uint8_t)inputString[0] >> 4 == MQTTSUBSCRIBE)) {
|
||||
strcpy(convBuf,inputString+(inputString[3]+4));
|
||||
msg.set(convBuf); //Payload
|
||||
} else {
|
||||
msg.set(""); //No payload
|
||||
}
|
||||
txBlink(1);
|
||||
if (!gw.sendRoute(build(msg, msg.destination, msg.sensor, C_SET, msg.type, 0))) errBlink(1);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void sendMQTT(const MyMessage &inMsg) {
|
||||
MyMessage msg = inMsg;
|
||||
buffsize = 0;
|
||||
if (!MQTTClientConnected) return; //We have no connections - return
|
||||
if (msg.isAck()) {
|
||||
// if (msg.sender==255 && mGetCommand(msg)==C_INTERNAL && msg.type==I_ID_REQUEST) {
|
||||
// TODO: sending ACK request on id_response fucks node up. doesn't work.
|
||||
// The idea was to confirm id and save to EEPROM_LATEST_NODE_ADDRESS.
|
||||
// }
|
||||
} else {
|
||||
// we have to check every message if its a newly assigned id or not.
|
||||
// Ack on I_ID_RESPONSE does not work, and checking on C_PRESENTATION isn't reliable.
|
||||
uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
|
||||
if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID;
|
||||
if (msg.sender==newNodeID) {
|
||||
gw.saveState(EEPROM_LATEST_NODE_ADDRESS,newNodeID);
|
||||
}
|
||||
if (mGetCommand(msg)==C_INTERNAL) {
|
||||
if (msg.type==I_CONFIG) {
|
||||
txBlink(1);
|
||||
if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_CONFIG, 0).set(MQTT_UNIT))) errBlink(1);
|
||||
return;
|
||||
} else if (msg.type==I_ID_REQUEST && msg.sender==255) {
|
||||
uint8_t newNodeID = gw.loadState(EEPROM_LATEST_NODE_ADDRESS)+1;
|
||||
if (newNodeID <= MQTT_FIRST_SENSORID) newNodeID = MQTT_FIRST_SENSORID;
|
||||
if (newNodeID >= MQTT_LAST_SENSORID) return; // Sorry no more id's left :(
|
||||
txBlink(1);
|
||||
if (!gw.sendRoute(build(msg, msg.sender, 255, C_INTERNAL, I_ID_RESPONSE, 0).set(newNodeID))) errBlink(1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (mGetCommand(msg)!=C_PRESENTATION) {
|
||||
if (mGetCommand(msg)==C_INTERNAL) msg.type=msg.type+(S_FIRSTCUSTOM-10); //Special message
|
||||
buffer[buffsize++] = MQTTPUBLISH << 4; // 0:
|
||||
buffer[buffsize++] = 0x09; // 1: Remaining length with no payload, we'll set this later to correct value, buffsize -2
|
||||
buffer[buffsize++] = 0x00; // 2: Length MSB (Remaing length can never exceed ff,so MSB must be 0!)
|
||||
buffer[buffsize++] = 0x08; // 3: Length LSB (ADDR), We'll set this later
|
||||
strcpy_P(buffer+4, broker);
|
||||
buffsize+=strlen_P(broker);
|
||||
#ifdef MQTT_TRANSLATE_TYPES
|
||||
if (msg.type > V_TOTAL) msg.type=V_UNKNOWN;// If type > defined types set to unknown.
|
||||
buffsize+=sprintf(&buffer[buffsize],"/%i/%i/V_%s",msg.sender,msg.sensor,getType(convBuf, &vType[msg.type]));
|
||||
#else
|
||||
buffsize+=sprintf(&buffer[buffsize],"/%i/%i/%i",msg.sender,msg.sensor,msg.type);
|
||||
#endif
|
||||
buffer[3]=buffsize-4; // Set correct address length on byte 4.
|
||||
#ifdef DEBUG
|
||||
Serial.println((char*)&buffer[4]);
|
||||
#endif
|
||||
msg.getString(convBuf);
|
||||
for (uint8_t a=0; a<strlen(convBuf); a++) {// Payload
|
||||
buffer[buffsize++] = convBuf[a];
|
||||
}
|
||||
buffer[1]=buffsize-2; // Set correct Remaining length on byte 2.
|
||||
writeEthernet(buffer,&buffsize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ledTimersInterrupt() {
|
||||
if(countRx && countRx != 255) {
|
||||
// switch led on
|
||||
digitalWrite(RADIO_RX_LED_PIN, LOW);
|
||||
} else if(!countRx) {
|
||||
// switching off
|
||||
digitalWrite(RADIO_RX_LED_PIN, HIGH);
|
||||
}
|
||||
if(countRx != 255) { countRx--; }
|
||||
|
||||
if(countTx && countTx != 255) {
|
||||
// switch led on
|
||||
digitalWrite(RADIO_TX_LED_PIN, LOW);
|
||||
} else if(!countTx) {
|
||||
// switching off
|
||||
digitalWrite(RADIO_TX_LED_PIN, HIGH);
|
||||
}
|
||||
if(countTx != 255) { countTx--; }
|
||||
|
||||
if(countErr && countErr != 255) {
|
||||
// switch led on
|
||||
digitalWrite(RADIO_ERROR_LED_PIN, LOW);
|
||||
} else if(!countErr) {
|
||||
// switching off
|
||||
digitalWrite(RADIO_ERROR_LED_PIN, HIGH);
|
||||
}
|
||||
if(countErr != 255) { countErr--; }
|
||||
|
||||
}
|
||||
|
||||
void rxBlink(uint8_t cnt) {
|
||||
if(countRx == 255) { countRx = cnt; }
|
||||
}
|
||||
void txBlink(uint8_t cnt) {
|
||||
if(countTx == 255) { countTx = cnt; }
|
||||
}
|
||||
void errBlink(uint8_t cnt) {
|
||||
if(countErr == 255) { countErr = cnt; }
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
The MySensors library adds a new layer on top of the RF24 library.
|
||||
It handles radio network routing, relaying and ids.
|
||||
|
||||
Created by Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
Modified by Daniel Wiegert
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifdef DEBUG
|
||||
#define TCPDUMP // Dump TCP packages
|
||||
#endif
|
||||
|
||||
#define MQTT_FIRST_SENSORID 20 // If you want manually configured nodes below this value. 255 = Disable
|
||||
#define MQTT_LAST_SENSORID 254 // 254 is max! 255 reserved.
|
||||
#define MQTT_BROKER_PREFIX "MyMQTT" // First prefix in MQTT tree, keep short!
|
||||
#define MQTT_SEND_SUBSCRIPTION 1 // Send empty payload (request) to node upon MQTT client subscribe request.
|
||||
// NOTE above : Beware to check if there is any length on payload in your incommingMessage code:
|
||||
// Example: if (msg.type==V_LIGHT && strlen(msg.getString())>0) otherwise the code might do strange things.
|
||||
#define MQTT_UNIT "M" // Select M for metric or I for imperial.
|
||||
#define MQTT_TRANSLATE_TYPES // V_TYPE in address, Comment if you want all numbers (MyMQTT/01/01/01)
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
#define EEPROM_LATEST_NODE_ADDRESS ((uint8_t)EEPROM_LOCAL_CONFIG_ADDRESS)
|
||||
#define MQTT_MAX_PACKET_SIZE 100
|
||||
|
||||
#define MQTTPROTOCOLVERSION 3
|
||||
#define MQTTCONNECT 1 // Client request to connect to Server
|
||||
#define MQTTCONNACK 2 // Connect Acknowledgment
|
||||
#define MQTTPUBLISH 3 // Publish message
|
||||
#define MQTTPUBACK 4 // Publish Acknowledgment
|
||||
#define MQTTPUBREC 5 // Publish Received (assured delivery part 1)
|
||||
#define MQTTPUBREL 6 // Publish Release (assured delivery part 2)
|
||||
#define MQTTPUBCOMP 7 // Publish Complete (assured delivery part 3)
|
||||
#define MQTTSUBSCRIBE 8 // Client Subscribe request
|
||||
#define MQTTSUBACK 9 // Subscribe Acknowledgment
|
||||
#define MQTTUNSUBSCRIBE 10 // Client Unsubscribe request
|
||||
#define MQTTUNSUBACK 11 // Unsubscribe Acknowledgment
|
||||
#define MQTTPINGREQ 12 // PING Request
|
||||
#define MQTTPINGRESP 13 // PING Response
|
||||
#define MQTTDISCONNECT 14 // Client is Disconnecting
|
||||
#define MQTTReserved 15 // Reserved
|
||||
|
||||
#define MQTTQOS0 (0 << 1)
|
||||
#define MQTTQOS1 (1 << 1)
|
||||
#define MQTTQOS2 (2 << 1)
|
||||
|
||||
#ifdef MQTT_TRANSLATE_TYPES
|
||||
|
||||
char V_0[] PROGMEM = "TEMP"; //V_TEMP
|
||||
char V_1[] PROGMEM = "HUM"; //V_HUM
|
||||
char V_2[] PROGMEM = "LIGHT"; //V_LIGHT
|
||||
char V_3[] PROGMEM = "DIMMER"; //V_DIMMER
|
||||
char V_4[] PROGMEM = "PRESSURE"; //V_PRESSURE
|
||||
char V_5[] PROGMEM = "FORECAST"; //V_FORECAST
|
||||
char V_6[] PROGMEM = "RAIN"; //V_RAIN
|
||||
char V_7[] PROGMEM = "RAINRATE"; //V_RAINRATE
|
||||
char V_8[] PROGMEM = "WIND"; //V_WIND
|
||||
char V_9[] PROGMEM = "GUST"; //V_GUST
|
||||
char V_10[] PROGMEM = "DIRECTON"; //V_DIRECTON
|
||||
char V_11[] PROGMEM = "UV"; //V_UV
|
||||
char V_12[] PROGMEM = "WEIGHT"; //V_WEIGHT
|
||||
char V_13[] PROGMEM = "DISTANCE"; //V_DISTANCE
|
||||
char V_14[] PROGMEM = "IMPEDANCE"; //V_IMPEDANCE
|
||||
char V_15[] PROGMEM = "ARMED"; //V_ARMED
|
||||
char V_16[] PROGMEM = "TRIPPED"; //V_TRIPPED
|
||||
char V_17[] PROGMEM = "WATT"; //V_WATT
|
||||
char V_18[] PROGMEM = "KWH"; //V_KWH
|
||||
char V_19[] PROGMEM = "SCENE_ON"; //V_SCENE_ON
|
||||
char V_20[] PROGMEM = "SCENE_OFF"; //V_SCENE_OFF
|
||||
char V_21[] PROGMEM = "HEATER"; //V_HEATER
|
||||
char V_22[] PROGMEM = "HEATER_SW"; //V_HEATER_SW
|
||||
char V_23[] PROGMEM = "LIGHT_LEVEL"; //V_LIGHT_LEVEL
|
||||
char V_24[] PROGMEM = "VAR1"; //V_VAR1
|
||||
char V_25[] PROGMEM = "VAR2"; //V_VAR2
|
||||
char V_26[] PROGMEM = "VAR3"; //V_VAR3
|
||||
char V_27[] PROGMEM = "VAR4"; //V_VAR4
|
||||
char V_28[] PROGMEM = "VAR5"; //V_VAR5
|
||||
char V_29[] PROGMEM = "UP"; //V_UP
|
||||
char V_30[] PROGMEM = "DOWN"; //V_DOWN
|
||||
char V_31[] PROGMEM = "STOP"; //V_STOP
|
||||
char V_32[] PROGMEM = "IR_SEND"; //V_IR_SEND
|
||||
char V_33[] PROGMEM = "IR_RECEIVE"; //V_IR_RECEIVE
|
||||
char V_34[] PROGMEM = "FLOW"; //V_FLOW
|
||||
char V_35[] PROGMEM = "VOLUME"; //V_VOLUME
|
||||
char V_36[] PROGMEM = "LOCK_STATUS"; //V_LOCK_STATUS
|
||||
char V_37[] PROGMEM = "DUST_LEVEL"; //V_DUST_LEVEL
|
||||
char V_38[] PROGMEM = "VOLTAGE"; //V_VOLTAGE
|
||||
char V_39[] PROGMEM = "CURRENT"; //V_CURRENT
|
||||
char V_40[] PROGMEM = ""; //
|
||||
char V_41[] PROGMEM = ""; //
|
||||
char V_42[] PROGMEM = ""; //
|
||||
char V_43[] PROGMEM = ""; //
|
||||
char V_44[] PROGMEM = ""; //
|
||||
char V_45[] PROGMEM = ""; //
|
||||
char V_46[] PROGMEM = ""; //
|
||||
char V_47[] PROGMEM = ""; //
|
||||
char V_48[] PROGMEM = ""; //
|
||||
char V_49[] PROGMEM = ""; //
|
||||
char V_50[] PROGMEM = ""; //
|
||||
char V_51[] PROGMEM = ""; //
|
||||
char V_52[] PROGMEM = ""; //
|
||||
char V_53[] PROGMEM = ""; //
|
||||
char V_54[] PROGMEM = ""; //
|
||||
char V_55[] PROGMEM = ""; //
|
||||
char V_56[] PROGMEM = ""; //
|
||||
char V_57[] PROGMEM = ""; //
|
||||
char V_58[] PROGMEM = ""; //
|
||||
char V_59[] PROGMEM = ""; //
|
||||
char V_60[] PROGMEM = "DEFAULT"; //Custom for MQTTGateway
|
||||
char V_61[] PROGMEM = "SKETCH_NAME"; //Custom for MQTTGateway
|
||||
char V_62[] PROGMEM = "SKETCH_VERSION"; //Custom for MQTTGateway
|
||||
char V_63[] PROGMEM = "UNKNOWN"; //Custom for MQTTGateway
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
|
||||
PROGMEM const char *vType[] = {
|
||||
V_0, V_1, V_2, V_3, V_4, V_5, V_6, V_7, V_8, V_9, V_10,
|
||||
V_11, V_12, V_13, V_14, V_15, V_16, V_17, V_18, V_19, V_20,
|
||||
V_21, V_22, V_23, V_24, V_25, V_26, V_27, V_28, V_29, V_30,
|
||||
V_31, V_32, V_33, V_34, V_35, V_36, V_37, V_38, V_39, V_40,
|
||||
V_41, V_42, V_43, V_44, V_45, V_46, V_47, V_48, V_49, V_50,
|
||||
V_51, V_52, V_53, V_54, V_55, V_56, V_57, V_58, V_59, V_60,
|
||||
V_61, V_62, V_63
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define S_FIRSTCUSTOM 60
|
||||
#define V_TOTAL (sizeof(vType)/sizeof(char *))-1
|
||||
|
||||
#endif
|
||||
|
||||
#define S_FIRSTCUSTOM 60
|
||||
#define V_UNKNOWN 63
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
# FakeMySensors
|
||||
Arduino sketch to fake sensor for the MySensors Library
|
||||
|
||||
This skecth is intended to crate fake sensors which register and respond to the controller
|
||||
|
||||
Barduino 2015
|
||||
-----------------
|
||||
|
||||
Comment/Uncomment the sensors you would like to test
|
||||
|
||||
Arduino Uno R3 can support about 12 sensors before it runs out of memory.
|
||||
You probably need to turn of the MySensor Lib debug to save some memory
|
||||
|
||||
Nest step will be to remove the read/write to the eprom
|
||||
and extend to support the v1.5 sensors
|
||||
@@ -1,3 +1,32 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Motion Sensor example using HC-SR501
|
||||
* http://www.mysensors.org/build/motion
|
||||
*
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
@@ -1,3 +1,32 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Pressure sensor example using BMP085 module
|
||||
* http://www.mysensors.org/build/pressure
|
||||
*
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
#include <Wire.h>
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
/*
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This sketch demonstrates how to use InterruptChain to receive and
|
||||
* decode remote switches (old and new) and remote sensors.
|
||||
*
|
||||
@@ -15,7 +38,6 @@
|
||||
* Setup:
|
||||
* - connect a 433MHz receiver on digital pin 2.
|
||||
*
|
||||
*
|
||||
* MySensor note: This example has not yet been adopted but can be used as an example
|
||||
* of receiving 433Mhz stuff.
|
||||
*
|
||||
|
||||
@@ -1,26 +1,47 @@
|
||||
/*
|
||||
RFID Lock sensor/actuator
|
||||
|
||||
Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
|
||||
Use RFID tag to lock/unlock a door or trigger a scene on your controller.
|
||||
This example sketch allows you to add an optional relay or solenoid
|
||||
which can be activated/opened by RFID or controller.
|
||||
|
||||
Use the I2C wiring option for your RFID module and connect to the following Arduino pins.
|
||||
|
||||
RFID Arduino
|
||||
----- -------
|
||||
GND -> GND
|
||||
VCC -> +5V
|
||||
SCL -> A5
|
||||
SDA -> A4
|
||||
|
||||
Use normal wiring for NRF24L01 radio
|
||||
|
||||
Attach a optional relay or solonoid lock to pin 4
|
||||
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* RFID Lock sensor/actuator
|
||||
*
|
||||
* Use RFID tag to lock/unlock a door or trigger a scene on your controller.
|
||||
* This example sketch allows you to add an optional relay or solenoid
|
||||
* which can be activated/opened by RFID or controller.
|
||||
*
|
||||
* Use the I2C wiring option for your RFID module and connect to the following Arduino pins.
|
||||
*
|
||||
* RFID Arduino
|
||||
* ----- -------
|
||||
* GND -> GND
|
||||
* VCC -> +5V
|
||||
* SCL -> A5
|
||||
* SDA -> A4
|
||||
*
|
||||
* Use normal wiring for NRF24L01 radio
|
||||
*
|
||||
* Attach a optional relay or solonoid lock to pin 4
|
||||
* http://www.mysensors.org/build/rfid
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
+40
-15
@@ -1,18 +1,43 @@
|
||||
|
||||
// Example sketch showing how to request time from controller which is stored in RTC module
|
||||
// The time and temperature (DS3231/DS3232) is shown on an attached Crystal LCD display
|
||||
//
|
||||
// Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
// Inspired by Gregl
|
||||
|
||||
// Wiring (radio wiring on www.mysensors.org)
|
||||
// ------------------------------------
|
||||
// Arduino RTC-Module I2C Display
|
||||
// ------------------------------------
|
||||
// GND GND GND
|
||||
// +5V VCC VCC
|
||||
// A4 SDA SDA
|
||||
// A5 SCL SCL
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to request time from controller which is stored in RTC module
|
||||
* The time and temperature (DS3231/DS3232) is shown on an attached Crystal LCD display
|
||||
*
|
||||
*
|
||||
* Wiring (radio wiring on www.mysensors.org)
|
||||
* ------------------------------------
|
||||
* Arduino RTC-Module I2C Display
|
||||
* ------------------------------------
|
||||
* GND GND GND
|
||||
* +5V VCC VCC
|
||||
* A4 SDA SDA
|
||||
* A5 SCL SCL
|
||||
*
|
||||
* http://www.mysensors.org/build/display
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,6 +1,36 @@
|
||||
// Example sketch showing how to control physical relays.
|
||||
// This example will remember relay state even after power failure.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to control physical relays.
|
||||
* This example will remember relay state after power failure.
|
||||
* http://www.mysensors.org/build/relay
|
||||
*/
|
||||
|
||||
#include <MySigningNone.h>
|
||||
#include <MyTransportNRF24.h>
|
||||
#include <MyTransportRFM69.h>
|
||||
#include <MyHwATMega328.h>
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -9,7 +39,15 @@
|
||||
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
|
||||
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
|
||||
|
||||
MySensor gw;
|
||||
// NRFRF24L01 radio driver (set low transmit power by default)
|
||||
MyTransportNRF24 radio(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
||||
//MyTransportRFM69 radio;
|
||||
// Message signing driver (none default)
|
||||
//MySigningNone signer;
|
||||
// Select AtMega328 hardware profile
|
||||
MyHwATMega328 hw;
|
||||
// Construct MySensors library
|
||||
MySensor gw(radio, hw);
|
||||
|
||||
void setup()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,33 @@
|
||||
// Example sketch för a "light switch" where you can control light or something
|
||||
// else from both vera and a local physical button (connected between digital
|
||||
// pin 3 and GND).
|
||||
// This node also works as a repeader for other nodes
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch for a "light switch" where you can control light or something
|
||||
* else from both HA controller and a local physical button
|
||||
* (connected between digital pin 3 and GND).
|
||||
* This node also works as a repeader for other nodes
|
||||
* http://www.mysensors.org/build/relay
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,7 +1,32 @@
|
||||
// Example sketch showing how to create a node thay repeates messages
|
||||
// from nodes far from gateway back to gateway.
|
||||
// It is important that nodes that has enabled repeater mode calls
|
||||
// gw.preocess() frequently. This node should never sleep.
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to create a node thay repeates messages
|
||||
* from nodes far from gateway back to gateway.
|
||||
* It is important that nodes that has enabled repeater mode calls
|
||||
* gw.process() frequently. Repeaters should never sleep.
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -1,28 +1,54 @@
|
||||
/* Secret Knock Sensor
|
||||
|
||||
See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct):
|
||||
https://learn.adafruit.com/secret-knock-activated-drawer-lock/
|
||||
Version 13.10.31 Built with Arduino IDE 1.0.5
|
||||
|
||||
By Steve Hoefer http://grathio.com
|
||||
Adapted to MySensors by Henrik Ekblad
|
||||
|
||||
Licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0
|
||||
http://creativecommons.org/licenses/by-nc-sa/3.0/us/
|
||||
(In short: Do what you want, as long as you credit me, don't relicense it, and don't sell it or use it in anything you sell without contacting me.)
|
||||
|
||||
------Wiring------
|
||||
Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND)
|
||||
Pin 1: Optional: Connect LED here (remember resisor in series)
|
||||
Pin 2: Optional: Piezo element (for beeps).
|
||||
Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg
|
||||
Pin 4: Connects to either 1. Relay which open door or lock or
|
||||
2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option).
|
||||
|
||||
|
||||
Connect radio according as usual(you can skip IRQ pin)
|
||||
http://www.mysensors.org/build/connect_radio
|
||||
*/
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* Secret Knock Sensor
|
||||
* http://www.mysensors.org/build/knock
|
||||
*
|
||||
* See original instructions here (note: The MySensors adopted code might differ in wiring. The instructions below is correct):
|
||||
* https://learn.adafruit.com/secret-knock-activated-drawer-lock/
|
||||
* Version 13.10.31 Built with Arduino IDE 1.0.5
|
||||
*
|
||||
* By Steve Hoefer http://grathio.com
|
||||
* Adapted to MySensors by Henrik Ekblad
|
||||
*
|
||||
* Licensed under Creative Commons Attribution-Noncommercial-Share Alike 3.0
|
||||
* http://creativecommons.org/licenses/by-nc-sa/3.0/us/
|
||||
* (In short: Do what you want, as long as you credit me, don't relicense it, and don't sell it or use it in anything you sell without contacting me.)
|
||||
*
|
||||
* ------Wiring------
|
||||
* Pin 0: Program button used for recording a new Knock (connect Pin0 -> button -> GND)
|
||||
* Pin 1: Optional: Connect LED here (remember resisor in series)
|
||||
* Pin 2: Optional: Piezo element (for beeps).
|
||||
* Pin 5: A sound sensor (digital output) for sensing knocks. See MySensors purchase guide. I used this: http://rover.ebay.com/rover/1/711-53200-19255-0/1?icep_ff3=2&pub=5575069610&toolid=10001&campid=5337433187&customid=&icep_item=200941260251&ipn=psmain&icep_vectorid=229466&kwid=902099&mtid=824&kw=lg
|
||||
* Pin 4: Connects to either 1. Relay which open door or lock or
|
||||
* 2. transistor that opens a solenoid lock when HIGH (see adafruit guide for this option).
|
||||
*
|
||||
*
|
||||
* Connect radio according as usual(you can skip IRQ pin)
|
||||
* http://www.mysensors.org/build/connect_radio
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Patrick "Anticimex" Fallberg <patrick@fallberg.net>
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to securely control locks.
|
||||
* This example will remember lock state even after power failure.
|
||||
*/
|
||||
|
||||
|
||||
#define USE_SOFTWARE_ATSHA // Disable to use ATSHA204A circuit
|
||||
|
||||
#include <MyTransportNRF24.h>
|
||||
#include <MyHwATMega328.h>
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
#ifdef USE_SOFTWARE_ATSHA
|
||||
#include <MySigningAtsha204Soft.h>
|
||||
#else
|
||||
#include <MySigningAtsha204.h>
|
||||
#endif
|
||||
|
||||
#define LOCK_1 3 // Arduino Digital I/O pin number for first lock (second on pin+1 etc)
|
||||
#define NOF_LOCKS 1 // Total number of attached locks
|
||||
#define LOCK_LOCK 1 // GPIO value to write to lock attached lock
|
||||
#define LOCK_UNLOCK 0 // GPIO value to write to unlock attached lock
|
||||
|
||||
MyTransportNRF24 radio; // NRFRF24L01 radio driver
|
||||
MyHwATMega328 hw; // Select AtMega328 hardware profile
|
||||
#ifdef MY_SIGNING_FEATURE
|
||||
#ifdef MY_SECURE_NODE_WHITELISTING
|
||||
#ifdef USE_SOFTWARE_ATSHA
|
||||
// Change the soft_serial value to an arbitrary value for proper security
|
||||
uint8_t soft_serial[SHA204_SERIAL_SZ] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09};
|
||||
#endif
|
||||
// We only use one whitelist entry (the gateway)
|
||||
whitelist_entry_t node_whitelist[] = {
|
||||
{ .nodeId = GATEWAY_ADDRESS,
|
||||
.serial = {0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01} }
|
||||
};
|
||||
#ifdef USE_SOFTWARE_ATSHA
|
||||
MySigningAtsha204Soft signer(true, 1, node_whitelist, soft_serial); // Message signing driver
|
||||
#else
|
||||
MySigningAtsha204 signer(true, 1, node_whitelist);
|
||||
#endif
|
||||
#else
|
||||
#ifdef USE_SOFTWARE_ATSHA
|
||||
MySigningAtsha204Soft signer;
|
||||
#else
|
||||
MySigningAtsha204 signer;
|
||||
#endif
|
||||
#endif
|
||||
MySensor gw(radio, hw, signer);
|
||||
#else
|
||||
#error SecureActuator cannot possibly be secure without signing enabled
|
||||
MySensor gw(radio, hw);
|
||||
#endif
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Initialize library and add callback for incoming messages (signing is required)
|
||||
gw.begin(incomingMessage, AUTO);
|
||||
// Send the sketch version information to the gateway and Controller
|
||||
gw.sendSketchInfo("Secure Lock", "1.0");
|
||||
|
||||
// Fetch lock status
|
||||
for (int lock=1, pin=LOCK_1; lock<=NOF_LOCKS;lock++, pin++) {
|
||||
// Register all locks to gw (they will be created as child devices)
|
||||
gw.present(lock, S_LOCK, false);
|
||||
// Then set lock pins in output mode
|
||||
pinMode(pin, OUTPUT);
|
||||
// Set lock to last known state (using eeprom storage)
|
||||
digitalWrite(pin, gw.loadState(lock)?LOCK_LOCK:LOCK_UNLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Alway process incoming messages whenever possible
|
||||
gw.process();
|
||||
}
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
// We only expect one type of message from controller. But we better check anyway.
|
||||
if (message.type==V_LOCK_STATUS && message.sensor<=NOF_LOCKS) {
|
||||
// Change relay state
|
||||
digitalWrite(message.sensor-1+LOCK_1, message.getBool()?LOCK_LOCK:LOCK_UNLOCK);
|
||||
// Store state in eeprom
|
||||
gw.saveState(message.sensor, message.getBool());
|
||||
// Write some debug info
|
||||
Serial.print("Incoming change for lock:");
|
||||
Serial.print(message.sensor);
|
||||
Serial.print(", New status: ");
|
||||
Serial.println(message.getBool());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <Wire.h>
|
||||
#include <SI7021.h>
|
||||
#include <SPI.h>
|
||||
#include <SPIFlash.h>
|
||||
#include "utility/SPIFlash.h"
|
||||
#include <EEPROM.h>
|
||||
#include <sha204_lib_return_codes.h>
|
||||
#include <sha204_library.h>
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GATEWAYUTIL_H__
|
||||
#define __GATEWAYUTIL_H__
|
||||
|
||||
#include <MyTransport.h>
|
||||
|
||||
|
||||
#ifdef ARDUINO
|
||||
|
||||
|
||||
uint8_t inclusionTime = 1; // Number of minutes inclusion mode is enabled
|
||||
uint8_t pinInclusion = 3; // Input pin that should trigger inclusion mode
|
||||
|
||||
#define MAX_RECEIVE_LENGTH 100 // Max buffersize needed for messages coming from controller
|
||||
#define MAX_SEND_LENGTH 120 // Max buffersize needed for messages destined for controller
|
||||
|
||||
volatile boolean buttonTriggeredInclusion;
|
||||
boolean inclusionMode; // Keeps track on inclusion mode
|
||||
void (*serial)(const char *fmt, ... );
|
||||
|
||||
MyParserSerial parser;
|
||||
|
||||
void setInclusionMode(boolean newMode);
|
||||
|
||||
char convBuf[MAX_PAYLOAD*2+1];
|
||||
char serialBuffer[MAX_SEND_LENGTH]; // Buffer for building string when sending data to vera
|
||||
unsigned long inclusionStartTime;
|
||||
|
||||
void setupGateway(uint8_t _inc, uint8_t _incTime, void (* _serial)(const char *, ... )) {
|
||||
inclusionMode = 0;
|
||||
buttonTriggeredInclusion = false;
|
||||
serial = _serial;
|
||||
|
||||
pinInclusion = _inc;
|
||||
inclusionTime = _incTime;
|
||||
|
||||
// Setup digital in that triggers inclusion mode
|
||||
pinMode(pinInclusion, INPUT);
|
||||
digitalWrite(pinInclusion, HIGH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void startInclusionInterrupt() {
|
||||
buttonTriggeredInclusion = true;
|
||||
}
|
||||
|
||||
void incomingMessage(const MyMessage &message) {
|
||||
// if (mGetCommand(message) == C_PRESENTATION && inclusionMode) {
|
||||
// gw.rxBlink(3);
|
||||
// } else {
|
||||
// gw.rxBlink(1);
|
||||
// }
|
||||
// Pass along the message from sensors to serial line
|
||||
serial(PSTR("%d;%d;%d;%d;%d;%s\n"),message.sender, message.sensor, mGetCommand(message), mGetAck(message), message.type, message.getString(convBuf));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void checkButtonTriggeredInclusion() {
|
||||
if (buttonTriggeredInclusion) {
|
||||
// Ok, someone pressed the inclusion button on the gateway
|
||||
// start inclusion mode for 1 munute.
|
||||
#ifdef DEBUG
|
||||
serial(PSTR("0;0;%d;0;%d;Inclusion started by button.\n"), C_INTERNAL, I_LOG_MESSAGE);
|
||||
#endif
|
||||
buttonTriggeredInclusion = false;
|
||||
setInclusionMode(true);
|
||||
}
|
||||
}
|
||||
|
||||
void checkInclusionFinished() {
|
||||
if (inclusionMode && millis()-inclusionStartTime>60000UL*inclusionTime) {
|
||||
// inclusionTimeInMinutes minute(s) has passed.. stop inclusion mode
|
||||
setInclusionMode(false);
|
||||
}
|
||||
}
|
||||
|
||||
void parseAndSend(MySensor &gw, char *commandBuffer) {
|
||||
boolean ok;
|
||||
MyMessage &msg = gw.getLastMessage();
|
||||
|
||||
if (parser.parse(msg, commandBuffer)) {
|
||||
uint8_t command = mGetCommand(msg);
|
||||
|
||||
if (msg.destination==GATEWAY_ADDRESS && command==C_INTERNAL) {
|
||||
// Handle messages directed to gateway
|
||||
if (msg.type == I_VERSION) {
|
||||
// Request for version
|
||||
serial(PSTR("0;0;%d;0;%d;%s\n"), C_INTERNAL, I_VERSION, LIBRARY_VERSION);
|
||||
} else if (msg.type == I_INCLUSION_MODE) {
|
||||
// Request to change inclusion mode
|
||||
setInclusionMode(atoi(msg.data) == 1);
|
||||
}
|
||||
} else {
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
gw.txBlink(1);
|
||||
#endif
|
||||
ok = gw.sendRoute(msg);
|
||||
if (!ok) {
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
gw.errBlink(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setInclusionMode(boolean newMode) {
|
||||
if (newMode != inclusionMode) {
|
||||
inclusionMode = newMode;
|
||||
// Send back mode change on serial line to ack command
|
||||
serial(PSTR("0;0;%d;0;%d;%d\n"), C_INTERNAL, I_INCLUSION_MODE, inclusionMode?1:0);
|
||||
|
||||
if (inclusionMode) {
|
||||
inclusionStartTime = millis();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
#error This example is only for use on Arduino.
|
||||
#endif // ARDUINO
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2013 Henrik Ekblad <henrik.ekblad@gmail.com>
|
||||
*
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* DESCRIPTION
|
||||
* The ArduinoGateway prints data received from sensors on the serial link.
|
||||
* The gateway accepts input on seral which will be sent out on radio network.
|
||||
@@ -12,42 +25,99 @@
|
||||
* The GW code is designed for Arduino Nano 328p / 16MHz
|
||||
*
|
||||
* Wire connections (OPTIONAL):
|
||||
* - Inclusion button should be connected between digital pin 3 and GND
|
||||
* - RX/TX/ERR leds need to be connected between +5V (anode) and digital ping 6/5/4 with resistor 270-330R in a series
|
||||
* - Inclusion button should be connected between digital pin 3 and GND
|
||||
* - RX/TX/ERR leds need to be connected between +5V (anode) and digital pin 6/5/4 with resistor 270-330R in a series
|
||||
*
|
||||
* LEDs (OPTIONAL):
|
||||
* - To use the feature, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
||||
* - RX (green) - blink fast on radio message recieved. In inclusion mode will blink fast only on presentation recieved
|
||||
* - TX (yellow) - blink fast on radio message transmitted. In inclusion mode will blink slowly
|
||||
* - ERR (red) - fast blink on error during transmission error or recieve crc error
|
||||
* - ERR (red) - fast blink on error during transmission error or recieve crc error
|
||||
*
|
||||
*/
|
||||
|
||||
#define NO_PORTB_PINCHANGES
|
||||
|
||||
#include <MySigningNone.h>
|
||||
#include <MyTransportRFM69.h>
|
||||
#include <MyTransportNRF24.h>
|
||||
#include <MyHwATMega328.h>
|
||||
#include <MySigningAtsha204Soft.h>
|
||||
#include <MySigningAtsha204.h>
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MyParserSerial.h>
|
||||
#include <MySensor.h>
|
||||
#include <MyGateway.h>
|
||||
#include <stdarg.h>
|
||||
#include <PinChangeInt.h>
|
||||
#include "GatewayUtil.h"
|
||||
|
||||
#define INCLUSION_MODE_TIME 1 // Number of minutes inclusion mode is enabled
|
||||
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
|
||||
#define INCLUSION_MODE_PIN 3 // Digital pin used for inclusion mode button
|
||||
#define RADIO_ERROR_LED_PIN 4 // Error led pin
|
||||
#define RADIO_RX_LED_PIN 6 // Receive led pin
|
||||
#define RADIO_TX_LED_PIN 5 // the PCB, on board LED
|
||||
|
||||
// NRFRF24L01 radio driver (set low transmit power by default)
|
||||
MyTransportNRF24 transport(RF24_CE_PIN, RF24_CS_PIN, RF24_PA_LEVEL_GW);
|
||||
//MyTransportRFM69 transport;
|
||||
|
||||
MyGateway gw(DEFAULT_CE_PIN, DEFAULT_CS_PIN, INCLUSION_MODE_TIME, INCLUSION_MODE_PIN, 6, 5, 4);
|
||||
// Message signing driver (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
//MySigningNone signer;
|
||||
//MySigningAtsha204Soft signer;
|
||||
//MySigningAtsha204 signer;
|
||||
|
||||
// Hardware profile
|
||||
MyHwATMega328 hw;
|
||||
|
||||
// Construct MySensors library (signer needed if MY_SIGNING_FEATURE is turned on in MyConfig.h)
|
||||
// To use LEDs blinking, uncomment WITH_LEDS_BLINKING in MyConfig.h
|
||||
#ifdef WITH_LEDS_BLINKING
|
||||
MySensor gw(transport, hw /*, signer*/, RADIO_RX_LED_PIN, RADIO_TX_LED_PIN, RADIO_ERROR_LED_PIN);
|
||||
#else
|
||||
MySensor gw(transport, hw /*, signer*/);
|
||||
#endif
|
||||
|
||||
char inputString[MAX_RECEIVE_LENGTH] = ""; // A string to hold incoming commands from serial/ethernet interface
|
||||
int inputPos = 0;
|
||||
boolean commandComplete = false; // whether the string is complete
|
||||
|
||||
void parseAndSend(char *commandBuffer);
|
||||
|
||||
void output(const char *fmt, ... ) {
|
||||
va_list args;
|
||||
va_start (args, fmt );
|
||||
vsnprintf_P(serialBuffer, MAX_SEND_LENGTH, fmt, args);
|
||||
va_end (args);
|
||||
Serial.print(serialBuffer);
|
||||
}
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
gw.begin();
|
||||
gw.begin(incomingMessage, 0, true, 0);
|
||||
|
||||
setupGateway(INCLUSION_MODE_PIN, INCLUSION_MODE_TIME, output);
|
||||
|
||||
// Add interrupt for inclusion button to pin
|
||||
PCintPort::attachInterrupt(pinInclusion, startInclusionInterrupt, RISING);
|
||||
|
||||
|
||||
// Send startup log message on serial
|
||||
serial(PSTR("0;0;%d;0;%d;Gateway startup complete.\n"), C_INTERNAL, I_GATEWAY_READY);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
gw.processRadioMessage();
|
||||
gw.process();
|
||||
|
||||
checkButtonTriggeredInclusion();
|
||||
checkInclusionFinished();
|
||||
|
||||
if (commandComplete) {
|
||||
// A command wass issued from serial interface
|
||||
// We will now try to send it to the actuator
|
||||
gw.parseAndSend(inputString);
|
||||
parseAndSend(gw, inputString);
|
||||
commandComplete = false;
|
||||
inputPos = 0;
|
||||
}
|
||||
@@ -83,3 +153,5 @@ void serialEvent() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,35 @@
|
||||
// Example showing how to create an atuator for a servo.
|
||||
// Connect red to +5V, Black or brown to GND and the last cable to Digital pin 3.
|
||||
// The servo consumes much power and should probably have its own powersource.'
|
||||
// The arduino might spontanally restart if too much power is used (happend
|
||||
// to me when servo tried to pass the extreme positions = full load).
|
||||
// Contribution by: Derek Macias
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
* Contribution by: Derek Macias
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example showing how to create an atuator for a servo.
|
||||
* Connect red to +5V, Black or brown to GND and the last cable to Digital pin 3.
|
||||
* The servo consumes much power and should probably have its own powersource.'
|
||||
* The arduino might spontanally restart if too much power is used (happend
|
||||
* to me when servo tried to pass the extreme positions = full load).
|
||||
* http://www.mysensors.org/build/servo
|
||||
*/
|
||||
|
||||
|
||||
#include <MySensor.h>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,31 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch sending soil moisture alarm to controller
|
||||
* http://www.mysensors.org/build/moisture
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Example sketch showing how to request time from controller.
|
||||
*/
|
||||
|
||||
// Example sketch showing how to request time from controller.
|
||||
// Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
+25
-2
@@ -1,5 +1,28 @@
|
||||
|
||||
/*
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* http://www.mysensors.org/build/scene_controller
|
||||
* Touch Display Scene Controller build using a touch enabled tft display
|
||||
* attached to a ATMega 2560. This example fetches time from controller and sends
|
||||
* in scene commands to the controller.
|
||||
|
||||
@@ -1,22 +1,43 @@
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - epierre
|
||||
* Contribution: bulldoglowell, gizmocuz
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Arduino UVM-30A
|
||||
* Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html
|
||||
* Because this table is pretty lineair, we can calculate a UVI with one decimal
|
||||
*
|
||||
* Connect sensor:
|
||||
*
|
||||
* + >>> 5V
|
||||
* - >>> GND
|
||||
* out >>> A0
|
||||
*
|
||||
* License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
/*
|
||||
Arduino UVM-30A
|
||||
|
||||
connect the sensor as follows :
|
||||
|
||||
+ >>> 5V
|
||||
- >>> GND
|
||||
out >>> A0
|
||||
|
||||
Contribution: epierre, bulldoglowell, gizmocuz
|
||||
|
||||
Index table taken from: http://www.elecrow.com/sensors-c-111/environment-c-111_112/uv-sensor-moduleuvm30a-p-716.html
|
||||
Because this table is pretty lineair, we can calculate a UVI with one decimal
|
||||
|
||||
License: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)
|
||||
*/
|
||||
|
||||
#include <MySensor.h>
|
||||
#include <SPI.h>
|
||||
|
||||
|
||||
@@ -1,13 +1,37 @@
|
||||
//
|
||||
// Use this sensor to measure volume and flow of your house watermeter.
|
||||
// You need to set the correct pulsefactor of your meter (pulses per m3).
|
||||
// The sensor starts by fetching current volume reading from gateway (VAR 1).
|
||||
// Reports both volume and flow back to gateway.
|
||||
//
|
||||
// Unfortunately millis() won't increment when the Arduino is in
|
||||
// sleepmode. So we cannot make this sensor sleep if we also want
|
||||
// to calculate/report flow.
|
||||
//
|
||||
/**
|
||||
* The MySensors Arduino library handles the wireless radio link and protocol
|
||||
* between your home built sensors/actuators and HA controller of choice.
|
||||
* The sensors forms a self healing radio network with optional repeaters. Each
|
||||
* repeater and gateway builds a routing tables in EEPROM which keeps track of the
|
||||
* network topology allowing messages to be routed to nodes.
|
||||
*
|
||||
* Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
|
||||
* Copyright (C) 2013-2015 Sensnology AB
|
||||
* Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
|
||||
*
|
||||
* Documentation: http://www.mysensors.org
|
||||
* Support Forum: http://forum.mysensors.org
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
*******************************
|
||||
*
|
||||
* REVISION HISTORY
|
||||
* Version 1.0 - Henrik Ekblad
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Use this sensor to measure volume and flow of your house watermeter.
|
||||
* You need to set the correct pulsefactor of your meter (pulses per m3).
|
||||
* The sensor starts by fetching current volume reading from gateway (VAR 1).
|
||||
* Reports both volume and flow back to gateway.
|
||||
*
|
||||
* Unfortunately millis() won't increment when the Arduino is in
|
||||
* sleepmode. So we cannot make this sensor sleep if we also want
|
||||
* to calculate/report flow.
|
||||
* http://www.mysensors.org/build/pulse_water
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
#include <MySensor.h>
|
||||
|
||||
@@ -0,0 +1,573 @@
|
||||
#include "Arduino.h"
|
||||
#include "ATSHA204.h"
|
||||
|
||||
// atsha204Class Constructor
|
||||
// Feed this function the Arduino-ized pin number you want to assign to the ATSHA204's SDA pin
|
||||
// This will find the DDRX, PORTX, and PINX registrs it'll need to point to to control that pin
|
||||
// As well as the bit value for each of those registers
|
||||
ATSHA204Class::ATSHA204Class(uint8_t pin)
|
||||
{
|
||||
device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin
|
||||
uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers
|
||||
|
||||
// Point to data direction register port of pin
|
||||
device_port_DDR = portModeRegister(port);
|
||||
// Point to output register of pin
|
||||
device_port_OUT = portOutputRegister(port);
|
||||
// Point to input register of pin
|
||||
device_port_IN = portInputRegister(port);
|
||||
}
|
||||
|
||||
void ATSHA204Class::getSerialNumber(uint8_t * response)
|
||||
{
|
||||
uint8_t readCommand[READ_COUNT];
|
||||
uint8_t readResponse[READ_4_RSP_SIZE];
|
||||
|
||||
/* read from bytes 0->3 of config zone */
|
||||
uint8_t returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN03);
|
||||
if (!returnCode)
|
||||
{
|
||||
for (int i=0; i<4; i++) // store bytes 0-3 into respones array
|
||||
response[i] = readResponse[SHA204_BUFFER_POS_DATA+i];
|
||||
|
||||
/* read from bytes 8->11 of config zone */
|
||||
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN47);
|
||||
|
||||
for (int i=4; i<8; i++) // store bytes 4-7 of SN into response array
|
||||
response[i] = readResponse[SHA204_BUFFER_POS_DATA+(i-4)];
|
||||
|
||||
if (!returnCode)
|
||||
{ /* Finally if last two reads were successful, read byte 8 of the SN */
|
||||
returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, ADDRESS_SN8);
|
||||
response[8] = readResponse[SHA204_BUFFER_POS_DATA]; // Byte 8 of SN should always be 0xEE
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* SWI bit bang functions */
|
||||
|
||||
void ATSHA204Class::swi_set_signal_pin(uint8_t is_high)
|
||||
{
|
||||
*device_port_DDR |= device_pin;
|
||||
|
||||
if (is_high)
|
||||
*device_port_OUT |= device_pin;
|
||||
else
|
||||
*device_port_OUT &= ~device_pin;
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::swi_send_bytes(uint8_t count, uint8_t *buffer)
|
||||
{
|
||||
uint8_t i, bit_mask;
|
||||
|
||||
// Disable interrupts while sending.
|
||||
noInterrupts(); //swi_disable_interrupts();
|
||||
|
||||
// Set signal pin as output.
|
||||
*device_port_OUT |= device_pin;
|
||||
*device_port_DDR |= device_pin;
|
||||
|
||||
// Wait turn around time.
|
||||
delayMicroseconds(RX_TX_DELAY); //RX_TX_DELAY;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
|
||||
{
|
||||
if (bit_mask & buffer[i])
|
||||
{
|
||||
*device_port_OUT &= ~device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
*device_port_OUT |= device_pin;
|
||||
delayMicroseconds(7*BIT_DELAY); //BIT_DELAY_7;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send a zero bit.
|
||||
*device_port_OUT &= ~device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
*device_port_OUT |= device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
*device_port_OUT &= ~device_pin;
|
||||
delayMicroseconds(BIT_DELAY); //BIT_DELAY_1;
|
||||
*device_port_OUT |= device_pin;
|
||||
delayMicroseconds(5*BIT_DELAY); //BIT_DELAY_5;
|
||||
}
|
||||
}
|
||||
}
|
||||
interrupts(); //swi_enable_interrupts();
|
||||
return SWI_FUNCTION_RETCODE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::swi_send_byte(uint8_t value)
|
||||
{
|
||||
return swi_send_bytes(1, &value);
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer)
|
||||
{
|
||||
uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS;
|
||||
uint8_t i;
|
||||
uint8_t bit_mask;
|
||||
uint8_t pulse_count;
|
||||
uint8_t timeout_count;
|
||||
|
||||
// Disable interrupts while receiving.
|
||||
noInterrupts(); //swi_disable_interrupts();
|
||||
|
||||
// Configure signal pin as input.
|
||||
*device_port_DDR &= ~device_pin;
|
||||
|
||||
// Receive bits and store in buffer.
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1)
|
||||
{
|
||||
pulse_count = 0;
|
||||
|
||||
// Make sure that the variable below is big enough.
|
||||
// Change it to uint16_t if 255 is too small, but be aware that
|
||||
// the loop resolution decreases on an 8-bit controller in that case.
|
||||
timeout_count = START_PULSE_TIME_OUT;
|
||||
|
||||
// Detect start bit.
|
||||
while (--timeout_count > 0)
|
||||
{
|
||||
// Wait for falling edge.
|
||||
if ((*device_port_IN & device_pin) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (timeout_count == 0)
|
||||
{
|
||||
status = SWI_FUNCTION_RETCODE_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Wait for rising edge.
|
||||
if ((*device_port_IN & device_pin) != 0)
|
||||
{
|
||||
// For an Atmel microcontroller this might be faster than "pulse_count++".
|
||||
pulse_count = 1;
|
||||
break;
|
||||
}
|
||||
} while (--timeout_count > 0);
|
||||
|
||||
if (pulse_count == 0)
|
||||
{
|
||||
status = SWI_FUNCTION_RETCODE_TIMEOUT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Trying to measure the time of start bit and calculating the timeout
|
||||
// for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU.
|
||||
// So let's just wait the maximum time for the falling edge of a zero bit
|
||||
// to arrive after we have detected the rising edge of the start bit.
|
||||
timeout_count = ZERO_PULSE_TIME_OUT;
|
||||
|
||||
// Detect possible edge indicating zero bit.
|
||||
do
|
||||
{
|
||||
if ((*device_port_IN & device_pin) == 0)
|
||||
{
|
||||
// For an Atmel microcontroller this might be faster than "pulse_count++".
|
||||
pulse_count = 2;
|
||||
break;
|
||||
}
|
||||
} while (--timeout_count > 0);
|
||||
|
||||
// Wait for rising edge of zero pulse before returning. Otherwise we might interpret
|
||||
// its rising edge as the next start pulse.
|
||||
if (pulse_count == 2)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((*device_port_IN & device_pin) != 0)
|
||||
break;
|
||||
} while (timeout_count-- > 0);
|
||||
}
|
||||
|
||||
// Update byte at current buffer index.
|
||||
else
|
||||
buffer[i] |= bit_mask; // received "one" bit
|
||||
}
|
||||
|
||||
if (status != SWI_FUNCTION_RETCODE_SUCCESS)
|
||||
break;
|
||||
}
|
||||
interrupts(); //swi_enable_interrupts();
|
||||
|
||||
if (status == SWI_FUNCTION_RETCODE_TIMEOUT)
|
||||
{
|
||||
if (i > 0)
|
||||
// Indicate that we timed out after having received at least one byte.
|
||||
status = SWI_FUNCTION_RETCODE_RX_FAIL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Physical functions */
|
||||
|
||||
void ATSHA204Class::sha204c_sleep()
|
||||
{
|
||||
swi_send_byte(SHA204_SWI_FLAG_SLEEP);
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::sha204p_receive_response(uint8_t size, uint8_t *response)
|
||||
{
|
||||
uint8_t count_byte;
|
||||
uint8_t i;
|
||||
uint8_t ret_code;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
response[i] = 0;
|
||||
|
||||
(void) swi_send_byte(SHA204_SWI_FLAG_TX);
|
||||
|
||||
ret_code = swi_receive_bytes(size, response);
|
||||
if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL)
|
||||
{
|
||||
count_byte = response[SHA204_BUFFER_POS_COUNT];
|
||||
if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size))
|
||||
return SHA204_INVALID_SIZE;
|
||||
|
||||
return SHA204_SUCCESS;
|
||||
}
|
||||
|
||||
// Translate error so that the Communication layer
|
||||
// can distinguish between a real error or the
|
||||
// device being busy executing a command.
|
||||
if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT)
|
||||
return SHA204_RX_NO_RESPONSE;
|
||||
else
|
||||
return SHA204_RX_FAIL;
|
||||
}
|
||||
|
||||
/* Communication functions */
|
||||
|
||||
uint8_t ATSHA204Class::sha204c_wakeup(uint8_t *response)
|
||||
{
|
||||
swi_set_signal_pin(0);
|
||||
delayMicroseconds(10*SHA204_WAKEUP_PULSE_WIDTH);
|
||||
swi_set_signal_pin(1);
|
||||
delay(SHA204_WAKEUP_DELAY);
|
||||
|
||||
uint8_t ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
return ret_code;
|
||||
|
||||
// Verify status response.
|
||||
if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN)
|
||||
ret_code = SHA204_INVALID_SIZE;
|
||||
else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP)
|
||||
ret_code = SHA204_COMM_FAIL;
|
||||
else
|
||||
{
|
||||
if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
|
||||
|| (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43))
|
||||
ret_code = SHA204_BAD_CRC;
|
||||
}
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
delay(SHA204_COMMAND_EXEC_MAX);
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::sha204c_resync(uint8_t size, uint8_t *response)
|
||||
{
|
||||
// Try to re-synchronize without sending a Wake token
|
||||
// (step 1 of the re-synchronization process).
|
||||
delay(SHA204_SYNC_TIMEOUT);
|
||||
uint8_t ret_code = sha204p_receive_response(size, response);
|
||||
if (ret_code == SHA204_SUCCESS)
|
||||
return ret_code;
|
||||
|
||||
// We lost communication. Send a Wake pulse and try
|
||||
// to receive a response (steps 2 and 3 of the
|
||||
// re-synchronization process).
|
||||
sha204c_sleep();
|
||||
ret_code = sha204c_wakeup(response);
|
||||
|
||||
// Translate a return value of success into one
|
||||
// that indicates that the device had to be woken up
|
||||
// and might have lost its TempKey.
|
||||
return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code);
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout)
|
||||
{
|
||||
uint8_t ret_code = SHA204_FUNC_FAIL;
|
||||
uint8_t ret_code_resync;
|
||||
uint8_t n_retries_send;
|
||||
uint8_t n_retries_receive;
|
||||
uint8_t i;
|
||||
uint8_t status_byte;
|
||||
uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT];
|
||||
uint8_t count_minus_crc = count - SHA204_CRC_SIZE;
|
||||
uint16_t execution_timeout_us = (uint16_t) (execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT;
|
||||
volatile uint16_t timeout_countdown;
|
||||
|
||||
// Append CRC.
|
||||
sha204c_calculate_crc(count_minus_crc, tx_buffer, tx_buffer + count_minus_crc);
|
||||
|
||||
// Retry loop for sending a command and receiving a response.
|
||||
n_retries_send = SHA204_RETRY_COUNT + 1;
|
||||
|
||||
while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS))
|
||||
{
|
||||
// Send command.
|
||||
ret_code = swi_send_byte(SHA204_SWI_FLAG_CMD);
|
||||
if (ret_code != SWI_FUNCTION_RETCODE_SUCCESS)
|
||||
ret_code = SHA204_COMM_FAIL;
|
||||
else
|
||||
ret_code = swi_send_bytes(count, tx_buffer);
|
||||
|
||||
if (ret_code != SHA204_SUCCESS)
|
||||
{
|
||||
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
|
||||
return ret_code; // The device seems to be dead in the water.
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait minimum command execution time and then start polling for a response.
|
||||
delay(execution_delay);
|
||||
|
||||
// Retry loop for receiving a response.
|
||||
n_retries_receive = SHA204_RETRY_COUNT + 1;
|
||||
while (n_retries_receive-- > 0)
|
||||
{
|
||||
// Reset response buffer.
|
||||
for (i = 0; i < rx_size; i++)
|
||||
rx_buffer[i] = 0;
|
||||
|
||||
// Poll for response.
|
||||
timeout_countdown = execution_timeout_us;
|
||||
do
|
||||
{
|
||||
ret_code = sha204p_receive_response(rx_size, rx_buffer);
|
||||
timeout_countdown -= SHA204_RESPONSE_TIMEOUT;
|
||||
}
|
||||
while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE));
|
||||
|
||||
if (ret_code == SHA204_RX_NO_RESPONSE)
|
||||
{
|
||||
// We did not receive a response. Re-synchronize and send command again.
|
||||
if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE)
|
||||
// The device seems to be dead in the water.
|
||||
return ret_code;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// Check whether we received a valid response.
|
||||
if (ret_code == SHA204_INVALID_SIZE)
|
||||
{
|
||||
// We see 0xFF for the count when communication got out of sync.
|
||||
ret_code_resync = sha204c_resync(rx_size, rx_buffer);
|
||||
if (ret_code_resync == SHA204_SUCCESS)
|
||||
// We did not have to wake up the device. Try receiving response again.
|
||||
continue;
|
||||
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
|
||||
// We could re-synchronize, but only after waking up the device.
|
||||
// Re-send command.
|
||||
break;
|
||||
else
|
||||
// We failed to re-synchronize.
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
// We received a response of valid size.
|
||||
// Check the consistency of the response.
|
||||
ret_code = sha204c_check_crc(rx_buffer);
|
||||
if (ret_code == SHA204_SUCCESS)
|
||||
{
|
||||
// Received valid response.
|
||||
if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN)
|
||||
// Received non-status response. We are done.
|
||||
return ret_code;
|
||||
|
||||
// Received status response.
|
||||
status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS];
|
||||
|
||||
// Translate the three possible device status error codes
|
||||
// into library return codes.
|
||||
if (status_byte == SHA204_STATUS_BYTE_PARSE)
|
||||
return SHA204_PARSE_ERROR;
|
||||
if (status_byte == SHA204_STATUS_BYTE_EXEC)
|
||||
return SHA204_CMD_FAIL;
|
||||
if (status_byte == SHA204_STATUS_BYTE_COMM)
|
||||
{
|
||||
// In case of the device status byte indicating a communication
|
||||
// error this function exits the retry loop for receiving a response
|
||||
// and enters the overall retry loop
|
||||
// (send command / receive response).
|
||||
ret_code = SHA204_STATUS_CRC;
|
||||
break;
|
||||
}
|
||||
|
||||
// Received status response from CheckMAC, DeriveKey, GenDig,
|
||||
// Lock, Nonce, Pause, UpdateExtra, or Write command.
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// Received response with incorrect CRC.
|
||||
ret_code_resync = sha204c_resync(rx_size, rx_buffer);
|
||||
if (ret_code_resync == SHA204_SUCCESS)
|
||||
// We did not have to wake up the device. Try receiving response again.
|
||||
continue;
|
||||
if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP)
|
||||
// We could re-synchronize, but only after waking up the device.
|
||||
// Re-send command.
|
||||
break;
|
||||
else
|
||||
// We failed to re-synchronize.
|
||||
return ret_code;
|
||||
} // block end of check response consistency
|
||||
|
||||
} // block end of receive retry loop
|
||||
|
||||
} // block end of send and receive retry loop
|
||||
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
|
||||
/* Marshaling functions */
|
||||
uint8_t ATSHA204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address)
|
||||
{
|
||||
uint8_t rx_size;
|
||||
|
||||
address >>= 2;
|
||||
|
||||
tx_buffer[SHA204_COUNT_IDX] = READ_COUNT;
|
||||
tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ;
|
||||
tx_buffer[READ_ZONE_IDX] = zone;
|
||||
tx_buffer[READ_ADDR_IDX] = (uint8_t) (address & SHA204_ADDRESS_MASK);
|
||||
tx_buffer[READ_ADDR_IDX + 1] = 0;
|
||||
|
||||
rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE;
|
||||
|
||||
return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], READ_DELAY, READ_EXEC_MAX - READ_DELAY);
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
|
||||
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer)
|
||||
{
|
||||
uint8_t poll_delay, poll_timeout, response_size;
|
||||
uint8_t *p_buffer;
|
||||
uint8_t len;
|
||||
|
||||
// Supply delays and response size.
|
||||
switch (op_code)
|
||||
{
|
||||
case SHA204_GENDIG:
|
||||
poll_delay = GENDIG_DELAY;
|
||||
poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY;
|
||||
response_size = GENDIG_RSP_SIZE;
|
||||
break;
|
||||
|
||||
case SHA204_HMAC:
|
||||
poll_delay = HMAC_DELAY;
|
||||
poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY;
|
||||
response_size = HMAC_RSP_SIZE;
|
||||
break;
|
||||
|
||||
case SHA204_NONCE:
|
||||
poll_delay = NONCE_DELAY;
|
||||
poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY;
|
||||
response_size = param1 == NONCE_MODE_PASSTHROUGH
|
||||
? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG;
|
||||
break;
|
||||
|
||||
case SHA204_RANDOM:
|
||||
poll_delay = RANDOM_DELAY;
|
||||
poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY;
|
||||
response_size = RANDOM_RSP_SIZE;
|
||||
break;
|
||||
|
||||
case SHA204_SHA:
|
||||
poll_delay = SHA_DELAY;
|
||||
poll_timeout = SHA_EXEC_MAX - SHA_DELAY;
|
||||
response_size = param1 == SHA_INIT
|
||||
? SHA_RSP_SIZE_SHORT : SHA_RSP_SIZE_LONG;
|
||||
break;
|
||||
|
||||
case SHA204_WRITE:
|
||||
poll_delay = WRITE_DELAY;
|
||||
poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY;
|
||||
response_size = WRITE_RSP_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
poll_delay = 0;
|
||||
poll_timeout = SHA204_COMMAND_EXEC_MAX;
|
||||
response_size = rx_size;
|
||||
}
|
||||
|
||||
// Assemble command.
|
||||
len = datalen1 + SHA204_CMD_SIZE_MIN;
|
||||
p_buffer = tx_buffer;
|
||||
*p_buffer++ = len;
|
||||
*p_buffer++ = op_code;
|
||||
*p_buffer++ = param1;
|
||||
*p_buffer++ = param2 & 0xFF;
|
||||
*p_buffer++ = param2 >> 8;
|
||||
|
||||
if (datalen1 > 0) {
|
||||
memcpy(p_buffer, data1, datalen1);
|
||||
p_buffer += datalen1;
|
||||
}
|
||||
|
||||
sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer);
|
||||
|
||||
// Send command and receive response.
|
||||
return sha204c_send_and_receive(&tx_buffer[0], response_size,
|
||||
&rx_buffer[0], poll_delay, poll_timeout);
|
||||
}
|
||||
|
||||
/* CRC Calculator and Checker */
|
||||
|
||||
void ATSHA204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc)
|
||||
{
|
||||
uint8_t counter;
|
||||
uint16_t crc_register = 0;
|
||||
uint16_t polynom = 0x8005;
|
||||
uint8_t shift_register;
|
||||
uint8_t data_bit, crc_bit;
|
||||
|
||||
for (counter = 0; counter < length; counter++)
|
||||
{
|
||||
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1)
|
||||
{
|
||||
data_bit = (data[counter] & shift_register) ? 1 : 0;
|
||||
crc_bit = crc_register >> 15;
|
||||
|
||||
// Shift CRC to the left by 1.
|
||||
crc_register <<= 1;
|
||||
|
||||
if ((data_bit ^ crc_bit) != 0)
|
||||
crc_register ^= polynom;
|
||||
}
|
||||
}
|
||||
crc[0] = (uint8_t) (crc_register & 0x00FF);
|
||||
crc[1] = (uint8_t) (crc_register >> 8);
|
||||
}
|
||||
|
||||
uint8_t ATSHA204Class::sha204c_check_crc(uint8_t *response)
|
||||
{
|
||||
uint8_t crc[SHA204_CRC_SIZE];
|
||||
uint8_t count = response[SHA204_BUFFER_POS_COUNT];
|
||||
|
||||
count -= SHA204_CRC_SIZE;
|
||||
sha204c_calculate_crc(count, response, crc);
|
||||
|
||||
return (crc[0] == response[count] && crc[1] == response[count + 1])
|
||||
? SHA204_SUCCESS : SHA204_BAD_CRC;
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
#ifndef ATSHA204_H
|
||||
#define ATSHA204_H
|
||||
#include "Arduino.h"
|
||||
|
||||
/* This is a scaled down variant of the ATSHA204 library, tweaked to meet the specific needs of MySensors. */
|
||||
|
||||
/* Library return codes */
|
||||
#define SHA204_SUCCESS ((uint8_t) 0x00) //!< Function succeeded.
|
||||
#define SHA204_PARSE_ERROR ((uint8_t) 0xD2) //!< response status byte indicates parsing error
|
||||
#define SHA204_CMD_FAIL ((uint8_t) 0xD3) //!< response status byte indicates command execution error
|
||||
#define SHA204_STATUS_CRC ((uint8_t) 0xD4) //!< response status byte indicates CRC error
|
||||
#define SHA204_STATUS_UNKNOWN ((uint8_t) 0xD5) //!< response status byte is unknown
|
||||
#define SHA204_FUNC_FAIL ((uint8_t) 0xE0) //!< Function could not execute due to incorrect condition / state.
|
||||
#define SHA204_GEN_FAIL ((uint8_t) 0xE1) //!< unspecified error
|
||||
#define SHA204_BAD_PARAM ((uint8_t) 0xE2) //!< bad argument (out of range, null pointer, etc.)
|
||||
#define SHA204_INVALID_ID ((uint8_t) 0xE3) //!< invalid device id, id not set
|
||||
#define SHA204_INVALID_SIZE ((uint8_t) 0xE4) //!< Count value is out of range or greater than buffer size.
|
||||
#define SHA204_BAD_CRC ((uint8_t) 0xE5) //!< incorrect CRC received
|
||||
#define SHA204_RX_FAIL ((uint8_t) 0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0.
|
||||
#define SHA204_RX_NO_RESPONSE ((uint8_t) 0xE7) //!< Not an error while the Command layer is polling for a command response.
|
||||
#define SHA204_RESYNC_WITH_WAKEUP ((uint8_t) 0xE8) //!< re-synchronization succeeded, but only after generating a Wake-up
|
||||
|
||||
#define SHA204_COMM_FAIL ((uint8_t) 0xF0) //!< Communication with device failed. Same as in hardware dependent modules.
|
||||
#define SHA204_TIMEOUT ((uint8_t) 0xF1) //!< Timed out while waiting for response. Number of bytes received is 0.
|
||||
|
||||
/* bitbang_config.h */
|
||||
|
||||
#define PORT_ACCESS_TIME (630) //! time it takes to toggle the pin at CPU clock of 16 MHz (ns)
|
||||
#define START_PULSE_WIDTH (4340) //! width of start pulse (ns)
|
||||
#define BIT_DELAY (4) //! delay macro for width of one pulse (start pulse or zero pulse, in ns)
|
||||
#define RX_TX_DELAY (15) //! turn around time when switching from receive to transmit
|
||||
#define START_PULSE_TIME_OUT (255) //! This value is decremented while waiting for the falling edge of a start pulse.
|
||||
#define ZERO_PULSE_TIME_OUT (26) //! This value is decremented while waiting for the falling edge of a zero pulse.
|
||||
|
||||
/* swi_phys.h */
|
||||
|
||||
#define SWI_FUNCTION_RETCODE_SUCCESS ((uint8_t) 0x00) //!< Communication with device succeeded.
|
||||
#define SWI_FUNCTION_RETCODE_TIMEOUT ((uint8_t) 0xF1) //!< Communication timed out.
|
||||
#define SWI_FUNCTION_RETCODE_RX_FAIL ((uint8_t) 0xF9) //!< Communication failed after at least one byte was received.
|
||||
|
||||
/* sha204_physical.h */
|
||||
|
||||
#define SHA204_RSP_SIZE_MIN ((uint8_t) 4) //!< minimum number of bytes in response
|
||||
#define SHA204_RSP_SIZE_MAX ((uint8_t) 35) //!< maximum size of response packet
|
||||
#define SHA204_BUFFER_POS_COUNT (0) //!< buffer index of count byte in command or response
|
||||
#define SHA204_BUFFER_POS_DATA (1) //!< buffer index of data in response
|
||||
#define SHA204_WAKEUP_PULSE_WIDTH (uint8_t) (6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! width of Wakeup pulse in 10 us units
|
||||
#define SHA204_WAKEUP_DELAY (uint8_t) (3.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! delay between Wakeup pulse and communication in ms
|
||||
|
||||
/* sha204_swi.c */
|
||||
#define SHA204_SWI_FLAG_CMD ((uint8_t) 0x77) //!< flag preceding a command
|
||||
#define SHA204_SWI_FLAG_TX ((uint8_t) 0x88) //!< flag requesting a response
|
||||
#define SHA204_SWI_FLAG_IDLE ((uint8_t) 0xBB) //!< flag requesting to go into Idle mode
|
||||
#define SHA204_SWI_FLAG_SLEEP ((uint8_t) 0xCC) //!< flag requesting to go into Sleep mode
|
||||
|
||||
/* sha204_comm_marshaling.h */
|
||||
// command op-code definitions
|
||||
#define SHA204_GENDIG ((uint8_t) 0x15) //!< GenDig command op-code
|
||||
#define SHA204_HMAC ((uint8_t) 0x11) //!< HMAC command op-code
|
||||
#define SHA204_NONCE ((uint8_t) 0x16) //!< Nonce command op-code
|
||||
#define SHA204_RANDOM ((uint8_t) 0x1B) //!< Random command op-code
|
||||
#define SHA204_READ ((uint8_t) 0x02) //!< Read command op-code
|
||||
#define SHA204_SHA ((uint8_t) 0x47) //!< SHA command op-code
|
||||
#define SHA204_WRITE ((uint8_t) 0x12) //!< Write command op-code
|
||||
|
||||
// packet size definitions
|
||||
#define SHA204_RSP_SIZE_VAL ((uint8_t) 7) //!< size of response packet containing four bytes of data
|
||||
|
||||
// definitions for command packet indexes common to all commands
|
||||
#define SHA204_COUNT_IDX ( 0) //!< command packet index for count
|
||||
#define SHA204_OPCODE_IDX ( 1) //!< command packet index for op-code
|
||||
#define SHA204_PARAM1_IDX ( 2) //!< command packet index for first parameter
|
||||
#define SHA204_PARAM2_IDX ( 3) //!< command packet index for second parameter
|
||||
#define SHA204_DATA_IDX ( 5) //!< command packet index for second parameter
|
||||
|
||||
// zone definitions
|
||||
#define SHA204_ZONE_CONFIG ((uint8_t) 0x00) //!< Configuration zone
|
||||
#define SHA204_ZONE_OTP ((uint8_t) 0x01) //!< OTP (One Time Programming) zone
|
||||
#define SHA204_ZONE_DATA ((uint8_t) 0x02) //!< Data zone
|
||||
#define SHA204_ZONE_MASK ((uint8_t) 0x03) //!< Zone mask
|
||||
#define SHA204_ZONE_COUNT_FLAG ((uint8_t) 0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes.
|
||||
#define SHA204_ZONE_ACCESS_4 ((uint8_t) 4) //!< Read or write 4 bytes.
|
||||
#define SHA204_ZONE_ACCESS_32 ((uint8_t) 32) //!< Read or write 32 bytes.
|
||||
#define SHA204_ADDRESS_MASK_CONFIG ( 0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone.
|
||||
#define SHA204_ADDRESS_MASK_OTP ( 0x000F) //!< Address bits 4 to 7 are 0 for OTP zone.
|
||||
#define SHA204_ADDRESS_MASK ( 0x007F) //!< Address bit 7 to 15 are always 0.
|
||||
|
||||
// GenDig command definitions
|
||||
#define GENDIG_ZONE_IDX SHA204_PARAM1_IDX //!< GenDig command index for zone
|
||||
#define GENDIG_KEYID_IDX SHA204_PARAM2_IDX //!< GenDig command index for key id
|
||||
#define GENDIG_DATA_IDX SHA204_DATA_IDX //!< GenDig command index for optional data
|
||||
#define GENDIG_COUNT SHA204_CMD_SIZE_MIN //!< GenDig command packet size without "other data"
|
||||
#define GENDIG_COUNT_DATA (11) //!< GenDig command packet size with "other data"
|
||||
#define GENDIG_OTHER_DATA_SIZE (4) //!< GenDig size of "other data"
|
||||
#define GENDIG_ZONE_CONFIG ((uint8_t) 0) //!< GenDig zone id config
|
||||
#define GENDIG_ZONE_OTP ((uint8_t) 1) //!< GenDig zone id OTP
|
||||
#define GENDIG_ZONE_DATA ((uint8_t) 2) //!< GenDig zone id data
|
||||
|
||||
// HMAC command definitions
|
||||
#define HMAC_MODE_IDX SHA204_PARAM1_IDX //!< HMAC command index for mode
|
||||
#define HMAC_KEYID_IDX SHA204_PARAM2_IDX //!< HMAC command index for key id
|
||||
#define HMAC_COUNT SHA204_CMD_SIZE_MIN //!< HMAC command packet size
|
||||
#define HMAC_MODE_MASK ((uint8_t) 0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0.
|
||||
#define HMAC_MODE_SOURCE_FLAG_MATCH ((uint8_t) 0x04) //!< HMAC mode bit 2: match TempKey.SourceFlag
|
||||
|
||||
// Nonce command definitions
|
||||
#define NONCE_MODE_IDX SHA204_PARAM1_IDX //!< Nonce command index for mode
|
||||
#define NONCE_PARAM2_IDX SHA204_PARAM2_IDX //!< Nonce command index for 2. parameter
|
||||
#define NONCE_INPUT_IDX SHA204_DATA_IDX //!< Nonce command index for input data
|
||||
#define NONCE_COUNT_SHORT (27) //!< Nonce command packet size for 20 bytes of data
|
||||
#define NONCE_COUNT_LONG (39) //!< Nonce command packet size for 32 bytes of data
|
||||
#define NONCE_MODE_MASK ((uint8_t) 3) //!< Nonce mode bits 2 to 7 are 0.
|
||||
#define NONCE_MODE_SEED_UPDATE ((uint8_t) 0x00) //!< Nonce mode: update seed
|
||||
#define NONCE_MODE_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Nonce mode: do not update seed
|
||||
#define NONCE_MODE_INVALID ((uint8_t) 0x02) //!< Nonce mode 2 is invalid.
|
||||
#define NONCE_MODE_PASSTHROUGH ((uint8_t) 0x03) //!< Nonce mode: pass-through
|
||||
#define NONCE_NUMIN_SIZE (20) //!< Nonce data length
|
||||
#define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce data length in pass-through mode (mode = 3)
|
||||
|
||||
// Random command definitions
|
||||
#define RANDOM_MODE_IDX SHA204_PARAM1_IDX //!< Random command index for mode
|
||||
#define RANDOM_PARAM2_IDX SHA204_PARAM2_IDX //!< Random command index for 2. parameter
|
||||
#define RANDOM_COUNT SHA204_CMD_SIZE_MIN //!< Random command packet size
|
||||
#define RANDOM_SEED_UPDATE ((uint8_t) 0x00) //!< Random mode for automatic seed update
|
||||
#define RANDOM_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Random mode for no seed update
|
||||
|
||||
// Read command definitions
|
||||
#define READ_ZONE_IDX SHA204_PARAM1_IDX //!< Read command index for zone
|
||||
#define READ_ADDR_IDX SHA204_PARAM2_IDX //!< Read command index for address
|
||||
#define READ_COUNT SHA204_CMD_SIZE_MIN //!< Read command packet size
|
||||
#define READ_ZONE_MASK ((uint8_t) 0x83) //!< Read zone bits 2 to 6 are 0.
|
||||
#define READ_ZONE_MODE_32_BYTES ((uint8_t) 0x80) //!< Read mode: 32 bytes
|
||||
|
||||
// SHA command definitions
|
||||
#define SHA_MODE_IDX SHA204_PARAM1_IDX //!< SHA command index for mode
|
||||
#define SHA_PARAM2_IDX SHA204_PARAM2_IDX //!< SHA command index for 2. parameter
|
||||
#define SHA_COUNT_SHORT SHA204_CMD_SIZE_MIN //!< SHA command packet size for init
|
||||
#define SHA_COUNT_LONG (71) //!< SHA command packet size for calculation
|
||||
#define SHA_MSG_SIZE (64) //!< SHA message data size
|
||||
#define SHA_INIT ((uint8_t) 0x00) //!< SHA mode for init
|
||||
#define SHA_CALC ((uint8_t) 0x01) //!< SHA mode for calculation
|
||||
|
||||
// Write command definitions
|
||||
#define WRITE_ZONE_IDX SHA204_PARAM1_IDX //!< Write command index for zone
|
||||
#define WRITE_ADDR_IDX SHA204_PARAM2_IDX //!< Write command index for address
|
||||
#define WRITE_VALUE_IDX SHA204_DATA_IDX //!< Write command index for data
|
||||
#define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data
|
||||
#define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data
|
||||
#define WRITE_COUNT_SHORT (11) //!< Write command packet size with short data and no MAC
|
||||
#define WRITE_COUNT_LONG (39) //!< Write command packet size with long data and no MAC
|
||||
#define WRITE_COUNT_SHORT_MAC (43) //!< Write command packet size with short data and MAC
|
||||
#define WRITE_COUNT_LONG_MAC (71) //!< Write command packet size with long data and MAC
|
||||
#define WRITE_MAC_SIZE (32) //!< Write MAC size
|
||||
#define WRITE_ZONE_MASK ((uint8_t) 0xC3) //!< Write zone bits 2 to 5 are 0.
|
||||
#define WRITE_ZONE_WITH_MAC ((uint8_t) 0x40) //!< Write zone bit 6: write encrypted with MAC
|
||||
|
||||
// Response size definitions
|
||||
#define GENDIG_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of GenDig command
|
||||
#define HMAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of HMAC command
|
||||
#define NONCE_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of Nonce command with mode[0:1] = 3
|
||||
#define NONCE_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of Nonce command
|
||||
#define RANDOM_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Random command
|
||||
#define READ_4_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of Read command when reading 4 bytes
|
||||
#define READ_32_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Read command when reading 32 bytes
|
||||
#define SHA_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of SHA command with mode[0:1] = 0
|
||||
#define SHA_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of SHA command
|
||||
#define WRITE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Write command
|
||||
|
||||
// command timing definitions for minimum execution times (ms)
|
||||
#define GENDIG_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define HMAC_DELAY ((uint8_t) (27.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define NONCE_DELAY ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define RANDOM_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define READ_DELAY ((uint8_t) ( 0.4 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define SHA_DELAY ((uint8_t) (11.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
#define WRITE_DELAY ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_NEGATIVE - 0.5))
|
||||
|
||||
// command timing definitions for maximum execution times (ms)
|
||||
#define GENDIG_EXEC_MAX ((uint8_t) (43.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define HMAC_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define NONCE_EXEC_MAX ((uint8_t) (60.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define RANDOM_EXEC_MAX ((uint8_t) (50.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define READ_EXEC_MAX ((uint8_t) ( 4.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define SHA_EXEC_MAX ((uint8_t) (22.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
#define WRITE_EXEC_MAX ((uint8_t) (42.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5))
|
||||
|
||||
/* from sha204_config.h */
|
||||
|
||||
#define CPU_CLOCK_DEVIATION_POSITIVE (1.01)
|
||||
#define CPU_CLOCK_DEVIATION_NEGATIVE (0.99)
|
||||
#define SHA204_RETRY_COUNT (1)
|
||||
#define SWI_RECEIVE_TIME_OUT ((uint16_t) 163) //! #START_PULSE_TIME_OUT in us instead of loop counts
|
||||
#define SWI_US_PER_BYTE ((uint16_t) 313) //! It takes 312.5 us to send a byte (9 single-wire bits / 230400 Baud * 8 flag bits).
|
||||
#define SHA204_SYNC_TIMEOUT ((uint8_t) 85)//! delay before sending a transmit flag in the synchronization routine
|
||||
#define SHA204_RESPONSE_TIMEOUT ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE) //! SWI response timeout is the sum of receive timeout and the time it takes to send the TX flag.
|
||||
|
||||
/* from sha204_comm.h */
|
||||
|
||||
#define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay
|
||||
#define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte)
|
||||
#define SHA204_CMD_SIZE_MAX ((uint8_t) SHA_COUNT_LONG) //! maximum size of command packet (SHA)
|
||||
#define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes
|
||||
#define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response
|
||||
#define SHA204_BUFFER_POS_DATA (1) //! buffer index of first data byte in data response
|
||||
#define SHA204_STATUS_BYTE_WAKEUP ((uint8_t) 0x11) //! command parse error
|
||||
#define SHA204_STATUS_BYTE_PARSE ((uint8_t) 0x03) //! command parse error
|
||||
#define SHA204_STATUS_BYTE_EXEC ((uint8_t) 0x0F) //! command execution error
|
||||
#define SHA204_STATUS_BYTE_COMM ((uint8_t) 0xFF) //! communication error
|
||||
|
||||
/* EEPROM Addresses */
|
||||
/* Configuration Zone */
|
||||
#define ADDRESS_SN03 0 // SN[0:3] are bytes 0->3 of configuration zone
|
||||
#define ADDRESS_RevNum 4 // bytes 4->7 of config zone are RevNum
|
||||
#define ADDRESS_SN47 8 // SN[4:7] are bytes 8->11 of config zone
|
||||
#define ADDRESS_SN8 12 // SN[8] is byte 12 of config zone, should be 0xEE
|
||||
#define ADDRESS_I2CEN 14 // I2C Enable, bit 0 represents I2C enable status
|
||||
#define ADDRESS_I2CADD 16 // Defines I2C address of SHA204
|
||||
#define ADDRESS_OTPMODE 18 // Sets the One-time-programmable mode
|
||||
#define ADDRESS_SELECTOR 19 // Controls writability of Selector
|
||||
|
||||
#define SHA204_SERIAL_SZ 9 // The number of bytes the serial number consists of
|
||||
|
||||
class ATSHA204Class
|
||||
{
|
||||
private:
|
||||
uint8_t device_pin;
|
||||
volatile uint8_t *device_port_DDR, *device_port_OUT, *device_port_IN;
|
||||
void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc);
|
||||
uint8_t sha204c_check_crc(uint8_t *response);
|
||||
void swi_set_signal_pin(uint8_t is_high);
|
||||
uint8_t swi_receive_bytes(uint8_t count, uint8_t *buffer);
|
||||
uint8_t swi_send_bytes(uint8_t count, uint8_t *buffer);
|
||||
uint8_t swi_send_byte(uint8_t value);
|
||||
uint8_t sha204p_receive_response(uint8_t size, uint8_t *response);
|
||||
uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, uint16_t address);
|
||||
uint8_t sha204c_wakeup(uint8_t *response);
|
||||
uint8_t sha204c_resync(uint8_t size, uint8_t *response);
|
||||
uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, uint8_t execution_timeout);
|
||||
public:
|
||||
ATSHA204Class(uint8_t pin); // Constructor
|
||||
void sha204c_sleep();
|
||||
uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2,
|
||||
uint8_t datalen1, uint8_t *data1, uint8_t tx_size, uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer);
|
||||
void getSerialNumber(uint8_t *response);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,856 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* LowPower Library
|
||||
* Version: 1.30
|
||||
* Date: 22-05-2013
|
||||
* Company: Rocket Scream Electronics
|
||||
* Website: www.rocketscream.com
|
||||
*
|
||||
* This is a lightweight low power library for Arduino. Please check our wiki
|
||||
* (www.rocketscream.com/wiki) for more information on using this piece of
|
||||
* library.
|
||||
*
|
||||
* This library is licensed under Creative Commons Attribution-ShareAlike 3.0
|
||||
* Unported License.
|
||||
*
|
||||
* Revision Description
|
||||
* ======== ===========
|
||||
* 1.30 Added support for ATMega168, ATMega2560, ATMega1280 & ATMega32U4.
|
||||
* Tested to work with Arduino IDE 1.0.1 - 1.0.4.
|
||||
* 1.20 Remove typo error in idle method for checking whether Timer 0 was
|
||||
* turned off.
|
||||
* Remove dependecy on WProgram.h which is not required.
|
||||
* Tested to work with Arduino IDE 1.0.
|
||||
* 1.10 Added #ifndef for sleep_bod_disable() for compatibility with future
|
||||
* Arduino IDE release.
|
||||
* 1.00 Initial public release.
|
||||
*******************************************************************************/
|
||||
#include <avr/sleep.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "LowPower.h"
|
||||
|
||||
// Only Pico Power devices can change BOD settings through software
|
||||
#if defined __AVR_ATmega328P__
|
||||
#ifndef sleep_bod_disable
|
||||
#define sleep_bod_disable() \
|
||||
do { \
|
||||
unsigned char tempreg; \
|
||||
__asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
|
||||
"ori %[tempreg], %[bods_bodse]" "\n\t" \
|
||||
"out %[mcucr], %[tempreg]" "\n\t" \
|
||||
"andi %[tempreg], %[not_bodse]" "\n\t" \
|
||||
"out %[mcucr], %[tempreg]" \
|
||||
: [tempreg] "=&d" (tempreg) \
|
||||
: [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
|
||||
[bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
|
||||
[not_bodse] "i" (~_BV(BODSE))); \
|
||||
} while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define lowPowerBodOn(mode) \
|
||||
do { \
|
||||
set_sleep_mode(mode); \
|
||||
cli(); \
|
||||
sleep_enable(); \
|
||||
sei(); \
|
||||
sleep_cpu(); \
|
||||
sleep_disable(); \
|
||||
sei(); \
|
||||
} while (0);
|
||||
|
||||
// Only Pico Power devices can change BOD settings through software
|
||||
#if defined __AVR_ATmega328P__
|
||||
#define lowPowerBodOff(mode)\
|
||||
do { \
|
||||
set_sleep_mode(mode); \
|
||||
cli(); \
|
||||
sleep_enable(); \
|
||||
sleep_bod_disable(); \
|
||||
sei(); \
|
||||
sleep_cpu(); \
|
||||
sleep_disable(); \
|
||||
sei(); \
|
||||
} while (0);
|
||||
#endif
|
||||
|
||||
// Some macros is still missing from AVR GCC distribution for ATmega32U4
|
||||
#if defined __AVR_ATmega32U4__
|
||||
// Timer 4 PRR bit is currently not defined in iom32u4.h
|
||||
#ifndef PRTIM4
|
||||
#define PRTIM4 4
|
||||
#endif
|
||||
|
||||
// Timer 4 power reduction macro is not defined currently in power.h
|
||||
#ifndef power_timer4_disable
|
||||
#define power_timer4_disable() (PRR1 |= (uint8_t)(1 << PRTIM4))
|
||||
#endif
|
||||
|
||||
#ifndef power_timer4_enable
|
||||
#define power_timer4_enable() (PRR1 &= (uint8_t)~(1 << PRTIM4))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: idle
|
||||
* Description: Putting ATmega328P/168 into idle state. Please make sure you
|
||||
* understand the implication and result of disabling module.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control:
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. timer2 Timer 2 module disable control:
|
||||
* (a) TIMER2_OFF - Turn off Timer 2 module
|
||||
* (b) TIMER2_ON - Leave Timer 2 module in its default state
|
||||
*
|
||||
* 4. timer1 Timer 1 module disable control:
|
||||
* (a) TIMER1_OFF - Turn off Timer 1 module
|
||||
* (b) TIMER1_ON - Leave Timer 1 module in its default state
|
||||
*
|
||||
* 5. timer0 Timer 0 module disable control:
|
||||
* (a) TIMER0_OFF - Turn off Timer 0 module
|
||||
* (b) TIMER0_ON - Leave Timer 0 module in its default state
|
||||
*
|
||||
* 6. spi SPI module disable control:
|
||||
* (a) SPI_OFF - Turn off SPI module
|
||||
* (b) SPI_ON - Leave SPI module in its default state
|
||||
*
|
||||
* 7. usart0 USART0 module disable control:
|
||||
* (a) USART0_OFF - Turn off USART0 module
|
||||
* (b) USART0_ON - Leave USART0 module in its default state
|
||||
*
|
||||
* 8. twi TWI module disable control:
|
||||
* (a) TWI_OFF - Turn off TWI module
|
||||
* (b) TWI_ON - Leave TWI module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168__)
|
||||
void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
|
||||
timer1_t timer1, timer0_t timer0,
|
||||
spi_t spi, usart0_t usart0, twi_t twi)
|
||||
{
|
||||
// Temporary clock source variable
|
||||
unsigned char clockSource = 0;
|
||||
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (TCCR2B & CS22) clockSource |= (1 << CS22);
|
||||
if (TCCR2B & CS21) clockSource |= (1 << CS21);
|
||||
if (TCCR2B & CS20) clockSource |= (1 << CS20);
|
||||
|
||||
// Remove the clock source to shutdown Timer2
|
||||
TCCR2B &= ~(1 << CS22);
|
||||
TCCR2B &= ~(1 << CS21);
|
||||
TCCR2B &= ~(1 << CS20);
|
||||
|
||||
power_timer2_disable();
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
power_adc_disable();
|
||||
}
|
||||
|
||||
if (timer1 == TIMER1_OFF) power_timer1_disable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_disable();
|
||||
if (spi == SPI_OFF) power_spi_disable();
|
||||
if (usart0 == USART0_OFF) power_usart0_disable();
|
||||
if (twi == TWI_OFF) power_twi_disable();
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
lowPowerBodOn(SLEEP_MODE_IDLE);
|
||||
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
power_adc_enable();
|
||||
ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (clockSource & CS22) TCCR2B |= (1 << CS22);
|
||||
if (clockSource & CS21) TCCR2B |= (1 << CS21);
|
||||
if (clockSource & CS20) TCCR2B |= (1 << CS20);
|
||||
|
||||
power_timer2_enable();
|
||||
}
|
||||
|
||||
if (timer1 == TIMER1_OFF) power_timer1_enable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_enable();
|
||||
if (spi == SPI_OFF) power_spi_enable();
|
||||
if (usart0 == USART0_OFF) power_usart0_enable();
|
||||
if (twi == TWI_OFF) power_twi_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: idle
|
||||
* Description: Putting ATmega32U4 into idle state. Please make sure you
|
||||
* understand the implication and result of disabling module.
|
||||
* Take note that Timer 2 is not available and USART0
|
||||
* is replaced with USART1 on ATmega32U4.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control:
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. timer4 Timer 4 module disable control:
|
||||
* (a) TIMER4_OFF - Turn off Timer 4 module
|
||||
* (b) TIMER4_ON - Leave Timer 4 module in its default state
|
||||
*
|
||||
* 4. timer3 Timer 3 module disable control:
|
||||
* (a) TIMER3_OFF - Turn off Timer 3 module
|
||||
* (b) TIMER3_ON - Leave Timer 3 module in its default state
|
||||
*
|
||||
* 5. timer1 Timer 1 module disable control:
|
||||
* (a) TIMER1_OFF - Turn off Timer 1 module
|
||||
* (b) TIMER1_ON - Leave Timer 1 module in its default state
|
||||
*
|
||||
* 6. timer0 Timer 0 module disable control:
|
||||
* (a) TIMER0_OFF - Turn off Timer 0 module
|
||||
* (b) TIMER0_ON - Leave Timer 0 module in its default state
|
||||
*
|
||||
* 7. spi SPI module disable control:
|
||||
* (a) SPI_OFF - Turn off SPI module
|
||||
* (b) SPI_ON - Leave SPI module in its default state
|
||||
*
|
||||
* 8. usart1 USART1 module disable control:
|
||||
* (a) USART1_OFF - Turn off USART1 module
|
||||
* (b) USART1_ON - Leave USART1 module in its default state
|
||||
*
|
||||
* 9. twi TWI module disable control:
|
||||
* (a) TWI_OFF - Turn off TWI module
|
||||
* (b) TWI_ON - Leave TWI module in its default state
|
||||
*
|
||||
* 10.usb USB module disable control:
|
||||
* (a) USB_OFF - Turn off USB module
|
||||
* (b) USB_ON - Leave USB module in its default state
|
||||
*******************************************************************************/
|
||||
#if defined __AVR_ATmega32U4__
|
||||
void LowPowerClass::idle(period_t period, adc_t adc,
|
||||
timer4_t timer4, timer3_t timer3,
|
||||
timer1_t timer1, timer0_t timer0,
|
||||
spi_t spi, usart1_t usart1, twi_t twi, usb_t usb)
|
||||
{
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
power_adc_disable();
|
||||
}
|
||||
|
||||
if (timer4 == TIMER4_OFF) power_timer4_disable();
|
||||
if (timer3 == TIMER3_OFF) power_timer3_disable();
|
||||
if (timer1 == TIMER1_OFF) power_timer1_disable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_disable();
|
||||
if (spi == SPI_OFF) power_spi_disable();
|
||||
if (usart1 == USART1_OFF) power_usart1_disable();
|
||||
if (twi == TWI_OFF) power_twi_disable();
|
||||
if (usb == USB_OFF) power_usb_disable();
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
lowPowerBodOn(SLEEP_MODE_IDLE);
|
||||
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
power_adc_enable();
|
||||
ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
if (timer4 == TIMER4_OFF) power_timer4_enable();
|
||||
if (timer3 == TIMER3_OFF) power_timer3_enable();
|
||||
if (timer1 == TIMER1_OFF) power_timer1_enable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_enable();
|
||||
if (spi == SPI_OFF) power_spi_enable();
|
||||
if (usart1 == USART1_OFF) power_usart1_enable();
|
||||
if (twi == TWI_OFF) power_twi_enable();
|
||||
if (usb == USB_OFF) power_usb_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: idle
|
||||
* Description: Putting ATmega2560 & ATmega1280 into idle state. Please make sure
|
||||
* you understand the implication and result of disabling module.
|
||||
* Take note that extra Timer 5, 4, 3 compared to an ATmega328P/168.
|
||||
* Also take note that extra USART 3, 2, 1 compared to an
|
||||
* ATmega328P/168.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control:
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. timer5 Timer 5 module disable control:
|
||||
* (a) TIMER5_OFF - Turn off Timer 5 module
|
||||
* (b) TIMER5_ON - Leave Timer 5 module in its default state
|
||||
*
|
||||
* 4. timer4 Timer 4 module disable control:
|
||||
* (a) TIMER4_OFF - Turn off Timer 4 module
|
||||
* (b) TIMER4_ON - Leave Timer 4 module in its default state
|
||||
*
|
||||
* 5. timer3 Timer 3 module disable control:
|
||||
* (a) TIMER3_OFF - Turn off Timer 3 module
|
||||
* (b) TIMER3_ON - Leave Timer 3 module in its default state
|
||||
*
|
||||
* 6. timer2 Timer 2 module disable control:
|
||||
* (a) TIMER2_OFF - Turn off Timer 2 module
|
||||
* (b) TIMER2_ON - Leave Timer 2 module in its default state
|
||||
*
|
||||
* 7. timer1 Timer 1 module disable control:
|
||||
* (a) TIMER1_OFF - Turn off Timer 1 module
|
||||
* (b) TIMER1_ON - Leave Timer 1 module in its default state
|
||||
*
|
||||
* 8. timer0 Timer 0 module disable control:
|
||||
* (a) TIMER0_OFF - Turn off Timer 0 module
|
||||
* (b) TIMER0_ON - Leave Timer 0 module in its default state
|
||||
*
|
||||
* 9. spi SPI module disable control:
|
||||
* (a) SPI_OFF - Turn off SPI module
|
||||
* (b) SPI_ON - Leave SPI module in its default state
|
||||
*
|
||||
* 10.usart3 USART3 module disable control:
|
||||
* (a) USART3_OFF - Turn off USART3 module
|
||||
* (b) USART3_ON - Leave USART3 module in its default state
|
||||
*
|
||||
* 11.usart2 USART2 module disable control:
|
||||
* (a) USART2_OFF - Turn off USART2 module
|
||||
* (b) USART2_ON - Leave USART2 module in its default state
|
||||
*
|
||||
* 12.usart1 USART1 module disable control:
|
||||
* (a) USART1_OFF - Turn off USART1 module
|
||||
* (b) USART1_ON - Leave USART1 module in its default state
|
||||
*
|
||||
* 13.usart0 USART0 module disable control:
|
||||
* (a) USART0_OFF - Turn off USART0 module
|
||||
* (b) USART0_ON - Leave USART0 module in its default state
|
||||
*
|
||||
* 14.twi TWI module disable control:
|
||||
* (a) TWI_OFF - Turn off TWI module
|
||||
* (b) TWI_ON - Leave TWI module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
#if defined (__AVR_ATmega2560__) || defined (__AVR_ATmega1280__)
|
||||
void LowPowerClass::idle(period_t period, adc_t adc, timer5_t timer5,
|
||||
timer4_t timer4, timer3_t timer3, timer2_t timer2,
|
||||
timer1_t timer1, timer0_t timer0, spi_t spi,
|
||||
usart3_t usart3, usart2_t usart2, usart1_t usart1,
|
||||
usart0_t usart0, twi_t twi)
|
||||
{
|
||||
// Temporary clock source variable
|
||||
unsigned char clockSource = 0;
|
||||
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (TCCR2B & CS22) clockSource |= (1 << CS22);
|
||||
if (TCCR2B & CS21) clockSource |= (1 << CS21);
|
||||
if (TCCR2B & CS20) clockSource |= (1 << CS20);
|
||||
|
||||
// Remove the clock source to shutdown Timer2
|
||||
TCCR2B &= ~(1 << CS22);
|
||||
TCCR2B &= ~(1 << CS21);
|
||||
TCCR2B &= ~(1 << CS20);
|
||||
|
||||
power_timer2_disable();
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
ADCSRA &= ~(1 << ADEN);
|
||||
power_adc_disable();
|
||||
}
|
||||
|
||||
if (timer5 == TIMER5_OFF) power_timer5_disable();
|
||||
if (timer4 == TIMER4_OFF) power_timer4_disable();
|
||||
if (timer3 == TIMER3_OFF) power_timer3_disable();
|
||||
if (timer1 == TIMER1_OFF) power_timer1_disable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_disable();
|
||||
if (spi == SPI_OFF) power_spi_disable();
|
||||
if (usart3 == USART3_OFF) power_usart3_disable();
|
||||
if (usart2 == USART2_OFF) power_usart2_disable();
|
||||
if (usart1 == USART1_OFF) power_usart1_disable();
|
||||
if (usart0 == USART0_OFF) power_usart0_disable();
|
||||
if (twi == TWI_OFF) power_twi_disable();
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
lowPowerBodOn(SLEEP_MODE_IDLE);
|
||||
|
||||
if (adc == ADC_OFF)
|
||||
{
|
||||
power_adc_enable();
|
||||
ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (clockSource & CS22) TCCR2B |= (1 << CS22);
|
||||
if (clockSource & CS21) TCCR2B |= (1 << CS21);
|
||||
if (clockSource & CS20) TCCR2B |= (1 << CS20);
|
||||
|
||||
power_timer2_enable();
|
||||
}
|
||||
|
||||
if (timer5 == TIMER5_OFF) power_timer5_enable();
|
||||
if (timer4 == TIMER4_OFF) power_timer4_enable();
|
||||
if (timer3 == TIMER3_OFF) power_timer3_enable();
|
||||
if (timer1 == TIMER1_OFF) power_timer1_enable();
|
||||
if (timer0 == TIMER0_OFF) power_timer0_enable();
|
||||
if (spi == SPI_OFF) power_spi_enable();
|
||||
if (usart3 == USART3_OFF) power_usart3_enable();
|
||||
if (usart2 == USART2_OFF) power_usart2_enable();
|
||||
if (usart1 == USART1_OFF) power_usart1_enable();
|
||||
if (usart0 == USART0_OFF) power_usart0_enable();
|
||||
if (twi == TWI_OFF) power_twi_enable();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: adcNoiseReduction
|
||||
* Description: Putting microcontroller into ADC noise reduction state. This is
|
||||
* a very useful state when using the ADC to achieve best and low
|
||||
* noise signal.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control. Turning off the ADC module is
|
||||
* basically removing the purpose of this low power mode.
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. timer2 Timer 2 module disable control:
|
||||
* (a) TIMER2_OFF - Turn off Timer 2 module
|
||||
* (b) TIMER2_ON - Leave Timer 2 module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
void LowPowerClass::adcNoiseReduction(period_t period, adc_t adc,
|
||||
timer2_t timer2)
|
||||
{
|
||||
// Temporary clock source variable
|
||||
unsigned char clockSource = 0;
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (TCCR2B & CS22) clockSource |= (1 << CS22);
|
||||
if (TCCR2B & CS21) clockSource |= (1 << CS21);
|
||||
if (TCCR2B & CS20) clockSource |= (1 << CS20);
|
||||
|
||||
// Remove the clock source to shutdown Timer2
|
||||
TCCR2B &= ~(1 << CS22);
|
||||
TCCR2B &= ~(1 << CS21);
|
||||
TCCR2B &= ~(1 << CS20);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
lowPowerBodOn(SLEEP_MODE_ADC);
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (clockSource & CS22) TCCR2B |= (1 << CS22);
|
||||
if (clockSource & CS21) TCCR2B |= (1 << CS21);
|
||||
if (clockSource & CS20) TCCR2B |= (1 << CS20);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: powerDown
|
||||
* Description: Putting microcontroller into power down state. This is
|
||||
* the lowest current consumption state. Use this together with
|
||||
* external pin interrupt to wake up through external event
|
||||
* triggering (example: RTC clockout pin, SD card detect pin).
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control. Turning off the ADC module is
|
||||
* basically removing the purpose of this low power mode.
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. bod Brown Out Detector (BOD) module disable control:
|
||||
* (a) BOD_OFF - Turn off BOD module
|
||||
* (b) BOD_ON - Leave BOD module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
void LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
|
||||
{
|
||||
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
if (bod == BOD_OFF)
|
||||
{
|
||||
#if defined __AVR_ATmega328P__
|
||||
lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
|
||||
#else
|
||||
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: powerSave
|
||||
* Description: Putting microcontroller into power save state. This is
|
||||
* the lowest current consumption state after power down.
|
||||
* Use this state together with an external 32.768 kHz crystal (but
|
||||
* 8/16 MHz crystal/resonator need to be removed) to provide an
|
||||
* asynchronous clock source to Timer 2. Please take note that
|
||||
* Timer 2 is also used by the Arduino core for PWM operation.
|
||||
* Please refer to wiring.c for explanation. Removal of the external
|
||||
* 8/16 MHz crystal/resonator requires the microcontroller to run
|
||||
* on its internal RC oscillator which is not so accurate for time
|
||||
* critical operation.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control. Turning off the ADC module is
|
||||
* basically removing the purpose of this low power mode.
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. bod Brown Out Detector (BOD) module disable control:
|
||||
* (a) BOD_OFF - Turn off BOD module
|
||||
* (b) BOD_ON - Leave BOD module in its default state
|
||||
*
|
||||
* 4. timer2 Timer 2 module disable control:
|
||||
* (a) TIMER2_OFF - Turn off Timer 2 module
|
||||
* (b) TIMER2_ON - Leave Timer 2 module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
void LowPowerClass::powerSave(period_t period, adc_t adc, bod_t bod,
|
||||
timer2_t timer2)
|
||||
{
|
||||
// Temporary clock source variable
|
||||
unsigned char clockSource = 0;
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (TCCR2B & CS22) clockSource |= (1 << CS22);
|
||||
if (TCCR2B & CS21) clockSource |= (1 << CS21);
|
||||
if (TCCR2B & CS20) clockSource |= (1 << CS20);
|
||||
|
||||
// Remove the clock source to shutdown Timer2
|
||||
TCCR2B &= ~(1 << CS22);
|
||||
TCCR2B &= ~(1 << CS21);
|
||||
TCCR2B &= ~(1 << CS20);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
if (bod == BOD_OFF)
|
||||
{
|
||||
#if defined __AVR_ATmega328P__
|
||||
lowPowerBodOff(SLEEP_MODE_PWR_SAVE);
|
||||
#else
|
||||
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (clockSource & CS22) TCCR2B |= (1 << CS22);
|
||||
if (clockSource & CS21) TCCR2B |= (1 << CS21);
|
||||
if (clockSource & CS20) TCCR2B |= (1 << CS20);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: powerStandby
|
||||
* Description: Putting microcontroller into power standby state.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control. Turning off the ADC module is
|
||||
* basically removing the purpose of this low power mode.
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. bod Brown Out Detector (BOD) module disable control:
|
||||
* (a) BOD_OFF - Turn off BOD module
|
||||
* (b) BOD_ON - Leave BOD module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
void LowPowerClass::powerStandby(period_t period, adc_t adc, bod_t bod)
|
||||
{
|
||||
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
|
||||
if (bod == BOD_OFF)
|
||||
{
|
||||
#if defined __AVR_ATmega328P__
|
||||
lowPowerBodOff(SLEEP_MODE_STANDBY);
|
||||
#else
|
||||
lowPowerBodOn(SLEEP_MODE_STANDBY);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lowPowerBodOn(SLEEP_MODE_STANDBY);
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: powerExtStandby
|
||||
* Description: Putting microcontroller into power extended standby state. This
|
||||
* is different from the power standby state as it has the
|
||||
* capability to run Timer 2 asynchronously.
|
||||
*
|
||||
* Argument Description
|
||||
* ========= ===========
|
||||
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
|
||||
* up resource:
|
||||
* (a) SLEEP_15MS - 15 ms sleep
|
||||
* (b) SLEEP_30MS - 30 ms sleep
|
||||
* (c) SLEEP_60MS - 60 ms sleep
|
||||
* (d) SLEEP_120MS - 120 ms sleep
|
||||
* (e) SLEEP_250MS - 250 ms sleep
|
||||
* (f) SLEEP_500MS - 500 ms sleep
|
||||
* (g) SLEEP_1S - 1 s sleep
|
||||
* (h) SLEEP_2S - 2 s sleep
|
||||
* (i) SLEEP_4S - 4 s sleep
|
||||
* (j) SLEEP_8S - 8 s sleep
|
||||
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
|
||||
*
|
||||
* 2. adc ADC module disable control.
|
||||
* (a) ADC_OFF - Turn off ADC module
|
||||
* (b) ADC_ON - Leave ADC module in its default state
|
||||
*
|
||||
* 3. bod Brown Out Detector (BOD) module disable control:
|
||||
* (a) BOD_OFF - Turn off BOD module
|
||||
* (b) BOD_ON - Leave BOD module in its default state
|
||||
*
|
||||
* 4. timer2 Timer 2 module disable control:
|
||||
* (a) TIMER2_OFF - Turn off Timer 2 module
|
||||
* (b) TIMER2_ON - Leave Timer 2 module in its default state
|
||||
*
|
||||
*******************************************************************************/
|
||||
void LowPowerClass::powerExtStandby(period_t period, adc_t adc, bod_t bod,
|
||||
timer2_t timer2)
|
||||
{
|
||||
// Temporary clock source variable
|
||||
unsigned char clockSource = 0;
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (TCCR2B & CS22) clockSource |= (1 << CS22);
|
||||
if (TCCR2B & CS21) clockSource |= (1 << CS21);
|
||||
if (TCCR2B & CS20) clockSource |= (1 << CS20);
|
||||
|
||||
// Remove the clock source to shutdown Timer2
|
||||
TCCR2B &= ~(1 << CS22);
|
||||
TCCR2B &= ~(1 << CS21);
|
||||
TCCR2B &= ~(1 << CS20);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
|
||||
|
||||
if (period != SLEEP_FOREVER)
|
||||
{
|
||||
wdt_enable(period);
|
||||
WDTCSR |= (1 << WDIE);
|
||||
}
|
||||
if (bod == BOD_OFF)
|
||||
{
|
||||
#if defined __AVR_ATmega328P__
|
||||
lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
|
||||
#else
|
||||
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
|
||||
}
|
||||
|
||||
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
|
||||
|
||||
#if !defined(__AVR_ATmega32U4__)
|
||||
if (timer2 == TIMER2_OFF)
|
||||
{
|
||||
if (clockSource & CS22) TCCR2B |= (1 << CS22);
|
||||
if (clockSource & CS21) TCCR2B |= (1 << CS21);
|
||||
if (clockSource & CS20) TCCR2B |= (1 << CS20);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Name: ISR (WDT_vect)
|
||||
* Description: Watchdog Timer interrupt service routine. This routine is
|
||||
* required to allow automatic WDIF and WDIE bit clearance in
|
||||
* hardware.
|
||||
*
|
||||
*******************************************************************************/
|
||||
ISR (WDT_vect)
|
||||
{
|
||||
// WDIE & WDIF is cleared in hardware upon entering this ISR
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
LowPowerClass LowPower;
|
||||
@@ -1,137 +0,0 @@
|
||||
#ifndef LowPower_h
|
||||
#define LowPower_h
|
||||
|
||||
enum period_t
|
||||
{
|
||||
SLEEP_15Ms,
|
||||
SLEEP_30MS,
|
||||
SLEEP_60MS,
|
||||
SLEEP_120MS,
|
||||
SLEEP_250MS,
|
||||
SLEEP_500MS,
|
||||
SLEEP_1S,
|
||||
SLEEP_2S,
|
||||
SLEEP_4S,
|
||||
SLEEP_8S,
|
||||
SLEEP_FOREVER
|
||||
};
|
||||
|
||||
enum bod_t
|
||||
{
|
||||
BOD_OFF,
|
||||
BOD_ON
|
||||
};
|
||||
|
||||
enum adc_t
|
||||
{
|
||||
ADC_OFF,
|
||||
ADC_ON
|
||||
};
|
||||
|
||||
enum timer5_t
|
||||
{
|
||||
TIMER5_OFF,
|
||||
TIMER5_ON
|
||||
};
|
||||
|
||||
enum timer4_t
|
||||
{
|
||||
TIMER4_OFF,
|
||||
TIMER4_ON
|
||||
};
|
||||
|
||||
enum timer3_t
|
||||
{
|
||||
TIMER3_OFF,
|
||||
TIMER3_ON
|
||||
};
|
||||
|
||||
enum timer2_t
|
||||
{
|
||||
TIMER2_OFF,
|
||||
TIMER2_ON
|
||||
};
|
||||
|
||||
enum timer1_t
|
||||
{
|
||||
TIMER1_OFF,
|
||||
TIMER1_ON
|
||||
};
|
||||
|
||||
enum timer0_t
|
||||
{
|
||||
TIMER0_OFF,
|
||||
TIMER0_ON
|
||||
};
|
||||
|
||||
enum spi_t
|
||||
{
|
||||
SPI_OFF,
|
||||
SPI_ON
|
||||
};
|
||||
|
||||
enum usart0_t
|
||||
{
|
||||
USART0_OFF,
|
||||
USART0_ON
|
||||
};
|
||||
|
||||
enum usart1_t
|
||||
{
|
||||
USART1_OFF,
|
||||
USART1_ON
|
||||
};
|
||||
|
||||
enum usart2_t
|
||||
{
|
||||
USART2_OFF,
|
||||
USART2_ON
|
||||
};
|
||||
|
||||
enum usart3_t
|
||||
{
|
||||
USART3_OFF,
|
||||
USART3_ON
|
||||
};
|
||||
|
||||
enum twi_t
|
||||
{
|
||||
TWI_OFF,
|
||||
TWI_ON
|
||||
};
|
||||
|
||||
enum usb_t
|
||||
{
|
||||
USB_OFF,
|
||||
USB_ON
|
||||
};
|
||||
|
||||
class LowPowerClass
|
||||
{
|
||||
public:
|
||||
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168__)
|
||||
void idle(period_t period, adc_t adc, timer2_t timer2,
|
||||
timer1_t timer1, timer0_t timer0, spi_t spi,
|
||||
usart0_t usart0, twi_t twi);
|
||||
#elif defined __AVR_ATmega2560__
|
||||
void idle(period_t period, adc_t adc, timer5_t timer5,
|
||||
timer4_t timer4, timer3_t timer3, timer2_t timer2,
|
||||
timer1_t timer1, timer0_t timer0, spi_t spi,
|
||||
usart3_t usart3, usart2_t usart2, usart1_t usart1,
|
||||
usart0_t usart0, twi_t twi);
|
||||
#elif defined __AVR_ATmega32U4__
|
||||
void idle(period_t period, adc_t adc, timer4_t timer4, timer3_t timer3,
|
||||
timer1_t timer1, timer0_t timer0, spi_t spi,
|
||||
usart1_t usart1, twi_t twi, usb_t usb);
|
||||
#else
|
||||
#error "Please ensure chosen MCU is either 328P, 32U4 or 2560."
|
||||
#endif
|
||||
void adcNoiseReduction(period_t period, adc_t adc, timer2_t timer2);
|
||||
void powerDown(period_t period, adc_t adc, bod_t bod);
|
||||
void powerSave(period_t period, adc_t adc, bod_t bod, timer2_t timer2);
|
||||
void powerStandby(period_t period, adc_t adc, bod_t bod);
|
||||
void powerExtStandby(period_t period, adc_t adc, bod_t bod, timer2_t timer2);
|
||||
};
|
||||
|
||||
extern LowPowerClass LowPower;
|
||||
#endif
|
||||
Executable → Regular
Executable → Regular
Executable → Regular
+5
-4
@@ -11,6 +11,7 @@
|
||||
|
||||
#ifndef __RF24_CONFIG_H__
|
||||
#define __RF24_CONFIG_H__
|
||||
#include <MyConfig.h>
|
||||
|
||||
#if ARDUINO < 100
|
||||
#include <WProgram.h>
|
||||
@@ -39,10 +40,10 @@
|
||||
#define _SPI uspi
|
||||
#elif defined SOFTSPI
|
||||
// change these pins to your liking
|
||||
//
|
||||
const uint8_t SOFT_SPI_MISO_PIN = 16;
|
||||
const uint8_t SOFT_SPI_MOSI_PIN = 15;
|
||||
const uint8_t SOFT_SPI_SCK_PIN = 14;
|
||||
//const uint8_t SOFT_SPI_MISO_PIN = 16; // <-- Moved to MyConfig.h
|
||||
//const uint8_t SOFT_SPI_MOSI_PIN = 15; // <-- Moved to MyConfig.h
|
||||
//const uint8_t SOFT_SPI_SCK_PIN = 14; // <-- Moved to MyConfig.h
|
||||
|
||||
const uint8_t SPI_MODE = 0;
|
||||
#define _SPI spi
|
||||
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
// **********************************************************************************
|
||||
// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H
|
||||
// **********************************************************************************
|
||||
// Copyright Felix Rusu (2014), felix@lowpowerlab.com
|
||||
// http://lowpowerlab.com/
|
||||
// **********************************************************************************
|
||||
// License
|
||||
// **********************************************************************************
|
||||
// This program is free software; you can redistribute it
|
||||
// and/or modify it under the terms of the GNU General
|
||||
// Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General
|
||||
// Public License along with this program; if not, write
|
||||
// to the Free Software Foundation, Inc.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// Licence can be viewed at
|
||||
// http://www.fsf.org/licenses/gpl.txt
|
||||
//
|
||||
// Please maintain this license information along with authorship
|
||||
// and copyright notices in any redistribution of this code
|
||||
// **********************************************************************************
|
||||
#include "RFM69.h"
|
||||
#include "RFM69registers.h"
|
||||
#include <SPI.h>
|
||||
|
||||
volatile byte RFM69::DATA[RF69_MAX_DATA_LEN];
|
||||
volatile byte RFM69::_mode; // current transceiver state
|
||||
volatile byte RFM69::DATALEN;
|
||||
volatile byte RFM69::SENDERID;
|
||||
volatile byte RFM69::TARGETID; //should match _address
|
||||
volatile byte RFM69::PAYLOADLEN;
|
||||
volatile byte RFM69::ACK_REQUESTED;
|
||||
volatile byte RFM69::ACK_RECEIVED; /// Should be polled immediately after sending a packet with ACK request
|
||||
volatile int RFM69::RSSI; //most accurate RSSI during reception (closest to the reception)
|
||||
RFM69* RFM69::selfPointer;
|
||||
|
||||
bool RFM69::initialize(byte freqBand, byte nodeID, byte networkID)
|
||||
{
|
||||
const byte CONFIG[][2] =
|
||||
{
|
||||
/* 0x01 */ { REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF | RF_OPMODE_STANDBY },
|
||||
/* 0x02 */ { REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET | RF_DATAMODUL_MODULATIONTYPE_FSK | RF_DATAMODUL_MODULATIONSHAPING_00 }, //no shaping
|
||||
/* 0x03 */ { REG_BITRATEMSB, RF_BITRATEMSB_55555}, //default:4.8 KBPS
|
||||
/* 0x04 */ { REG_BITRATELSB, RF_BITRATELSB_55555},
|
||||
/* 0x05 */ { REG_FDEVMSB, RF_FDEVMSB_50000}, //default:5khz, (FDEV + BitRate/2 <= 500Khz)
|
||||
/* 0x06 */ { REG_FDEVLSB, RF_FDEVLSB_50000},
|
||||
|
||||
/* 0x07 */ { REG_FRFMSB, (freqBand==RF69_315MHZ ? RF_FRFMSB_315 : (freqBand==RF69_433MHZ ? RF_FRFMSB_433 : (freqBand==RF69_868MHZ ? RF_FRFMSB_868 : RF_FRFMSB_915))) },
|
||||
/* 0x08 */ { REG_FRFMID, (freqBand==RF69_315MHZ ? RF_FRFMID_315 : (freqBand==RF69_433MHZ ? RF_FRFMID_433 : (freqBand==RF69_868MHZ ? RF_FRFMID_868 : RF_FRFMID_915))) },
|
||||
/* 0x09 */ { REG_FRFLSB, (freqBand==RF69_315MHZ ? RF_FRFLSB_315 : (freqBand==RF69_433MHZ ? RF_FRFLSB_433 : (freqBand==RF69_868MHZ ? RF_FRFLSB_868 : RF_FRFLSB_915))) },
|
||||
|
||||
// looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
|
||||
// +17dBm and +20dBm are possible on RFM69HW
|
||||
// +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**)
|
||||
// +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)**
|
||||
// +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
|
||||
///* 0x11 */ { REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111},
|
||||
///* 0x13 */ { REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95 }, //over current protection (default is 95mA)
|
||||
|
||||
// RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4khz)
|
||||
/* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2 }, //(BitRate < 2 * RxBw)
|
||||
//for BR-19200: //* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 },
|
||||
/* 0x25 */ { REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01 }, //DIO0 is the only IRQ we're using
|
||||
/* 0x29 */ { REG_RSSITHRESH, 220 }, //must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm
|
||||
///* 0x2d */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA
|
||||
/* 0x2e */ { REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0 },
|
||||
/* 0x2f */ { REG_SYNCVALUE1, 0x2D }, //attempt to make this compatible with sync1 byte of RFM12B lib
|
||||
/* 0x30 */ { REG_SYNCVALUE2, networkID }, //NETWORK ID
|
||||
/* 0x37 */ { REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF },
|
||||
/* 0x38 */ { REG_PAYLOADLENGTH, 66 }, //in variable length mode: the max frame size, not used in TX
|
||||
//* 0x39 */ { REG_NODEADRS, nodeID }, //turned off because we're not using address filtering
|
||||
/* 0x3C */ { REG_FIFOTHRESH, RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE }, //TX on FIFO not empty
|
||||
/* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
|
||||
//for BR-19200: //* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
|
||||
//* 0x6F */ { REG_TESTDAGC, RF_DAGC_CONTINUOUS }, // run DAGC continuously in RX mode
|
||||
/* 0x6F */ { REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0 }, // run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0
|
||||
{255, 0}
|
||||
};
|
||||
|
||||
pinMode(_slaveSelectPin, OUTPUT);
|
||||
SPI.begin();
|
||||
|
||||
do writeReg(REG_SYNCVALUE1, 0xaa); while (readReg(REG_SYNCVALUE1) != 0xaa);
|
||||
do writeReg(REG_SYNCVALUE1, 0x55); while (readReg(REG_SYNCVALUE1) != 0x55);
|
||||
|
||||
for (byte i = 0; CONFIG[i][0] != 255; i++)
|
||||
writeReg(CONFIG[i][0], CONFIG[i][1]);
|
||||
|
||||
// Encryption is persistent between resets and can trip you up during debugging.
|
||||
// Disable it during initialization so we always start from a known state.
|
||||
encrypt(0);
|
||||
|
||||
setHighPower(_isRFM69HW); //called regardless if it's a RFM69W or RFM69HW
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady
|
||||
attachInterrupt(_interruptNum, RFM69::isr0, RISING);
|
||||
|
||||
selfPointer = this;
|
||||
_address = nodeID;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RFM69::setFrequency(uint32_t FRF)
|
||||
{
|
||||
writeReg(REG_FRFMSB, FRF >> 16);
|
||||
writeReg(REG_FRFMID, FRF >> 8);
|
||||
writeReg(REG_FRFLSB, FRF);
|
||||
}
|
||||
|
||||
void RFM69::setMode(byte newMode)
|
||||
{
|
||||
if (newMode == _mode) return; //TODO: can remove this?
|
||||
|
||||
switch (newMode) {
|
||||
case RF69_MODE_TX:
|
||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_TRANSMITTER);
|
||||
if (_isRFM69HW) setHighPowerRegs(true);
|
||||
break;
|
||||
case RF69_MODE_RX:
|
||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_RECEIVER);
|
||||
if (_isRFM69HW) setHighPowerRegs(false);
|
||||
break;
|
||||
case RF69_MODE_SYNTH:
|
||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SYNTHESIZER);
|
||||
break;
|
||||
case RF69_MODE_STANDBY:
|
||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_STANDBY);
|
||||
break;
|
||||
case RF69_MODE_SLEEP:
|
||||
writeReg(REG_OPMODE, (readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP);
|
||||
break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
// we are using packet mode, so this check is not really needed
|
||||
// but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
|
||||
while (_mode == RF69_MODE_SLEEP && (readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady
|
||||
|
||||
_mode = newMode;
|
||||
}
|
||||
|
||||
void RFM69::sleep() {
|
||||
setMode(RF69_MODE_SLEEP);
|
||||
}
|
||||
|
||||
void RFM69::setAddress(byte addr)
|
||||
{
|
||||
_address = addr;
|
||||
writeReg(REG_NODEADRS, _address);
|
||||
}
|
||||
|
||||
// set output power: 0=min, 31=max
|
||||
// this results in a "weaker" transmitted signal, and directly results in a lower RSSI at the receiver
|
||||
void RFM69::setPowerLevel(byte powerLevel)
|
||||
{
|
||||
_powerLevel = powerLevel;
|
||||
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0xE0) | (_powerLevel > 31 ? 31 : _powerLevel));
|
||||
}
|
||||
|
||||
bool RFM69::canSend()
|
||||
{
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN == 0 && readRSSI() < CSMA_LIMIT) //if signal stronger than -100dBm is detected assume channel activity
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void RFM69::send(byte toAddress, const void* buffer, byte bufferSize, bool requestACK)
|
||||
{
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
long now = millis();
|
||||
while (!canSend() && millis()-now < RF69_CSMA_LIMIT_MS) receiveDone();
|
||||
sendFrame(toAddress, buffer, bufferSize, requestACK, false);
|
||||
}
|
||||
|
||||
// to increase the chance of getting a packet across, call this function instead of send
|
||||
// and it handles all the ACK requesting/retrying for you :)
|
||||
// The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs
|
||||
// The reason for the semi-automaton is that the lib is ingterrupt driven and
|
||||
// requires user action to read the received data and decide what to do with it
|
||||
// replies usually take only 5-8ms at 50kbps@915Mhz
|
||||
bool RFM69::sendWithRetry(byte toAddress, const void* buffer, byte bufferSize, byte retries, byte retryWaitTime) {
|
||||
long sentTime;
|
||||
for (byte i=0; i<=retries; i++)
|
||||
{
|
||||
send(toAddress, buffer, bufferSize, true);
|
||||
sentTime = millis();
|
||||
while (millis()-sentTime<retryWaitTime)
|
||||
{
|
||||
if (ACKReceived(toAddress))
|
||||
{
|
||||
//Serial.print(" ~ms:");Serial.print(millis()-sentTime);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
//Serial.print(" RETRY#");Serial.println(i+1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Should be polled immediately after sending a packet with ACK request
|
||||
bool RFM69::ACKReceived(byte fromNodeID) {
|
||||
if (receiveDone())
|
||||
return (SENDERID == fromNodeID || fromNodeID == RF69_BROADCAST_ADDR) && ACK_RECEIVED;
|
||||
return false;
|
||||
}
|
||||
|
||||
//check whether an ACK was requested in the last received packet (non-broadcasted packet)
|
||||
bool RFM69::ACKRequested() {
|
||||
return ACK_REQUESTED && (TARGETID != RF69_BROADCAST_ADDR);
|
||||
}
|
||||
|
||||
/// Should be called immediately after reception in case sender wants ACK
|
||||
void RFM69::sendACK(const void* buffer, byte bufferSize) {
|
||||
byte sender = SENDERID;
|
||||
while (!canSend()) receiveDone();
|
||||
sendFrame(sender, buffer, bufferSize, false, true);
|
||||
}
|
||||
|
||||
void RFM69::sendFrame(byte toAddress, const void* buffer, byte bufferSize, bool requestACK, bool sendACK)
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY); //turn off receiver to prevent reception while filling fifo
|
||||
while ((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00); // Wait for ModeReady
|
||||
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00); // DIO0 is "Packet Sent"
|
||||
if (bufferSize > RF69_MAX_DATA_LEN) bufferSize = RF69_MAX_DATA_LEN;
|
||||
|
||||
//write to FIFO
|
||||
select();
|
||||
SPI.transfer(REG_FIFO | 0x80);
|
||||
SPI.transfer(bufferSize + 3);
|
||||
SPI.transfer(toAddress);
|
||||
SPI.transfer(_address);
|
||||
|
||||
//control byte
|
||||
if (sendACK)
|
||||
SPI.transfer(0x80);
|
||||
else if (requestACK)
|
||||
SPI.transfer(0x40);
|
||||
else SPI.transfer(0x00);
|
||||
|
||||
for (byte i = 0; i < bufferSize; i++)
|
||||
SPI.transfer(((byte*)buffer)[i]);
|
||||
unselect();
|
||||
|
||||
/* no need to wait for transmit mode to be ready since its handled by the radio */
|
||||
setMode(RF69_MODE_TX);
|
||||
while (digitalRead(_interruptPin) == 0); //wait for DIO0 to turn HIGH signalling transmission finish
|
||||
//while (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PACKETSENT == 0x00); // Wait for ModeReady
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
}
|
||||
|
||||
void RFM69::interruptHandler() {
|
||||
//pinMode(4, OUTPUT);
|
||||
//digitalWrite(4, 1);
|
||||
if (_mode == RF69_MODE_RX && (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY))
|
||||
{
|
||||
//RSSI = readRSSI();
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
select();
|
||||
SPI.transfer(REG_FIFO & 0x7f);
|
||||
PAYLOADLEN = SPI.transfer(0);
|
||||
PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; //precaution
|
||||
TARGETID = SPI.transfer(0);
|
||||
if(!(_promiscuousMode || TARGETID==_address || TARGETID==RF69_BROADCAST_ADDR)) //match this node's address, or broadcast address or anything in promiscuous mode
|
||||
{
|
||||
PAYLOADLEN = 0;
|
||||
unselect();
|
||||
//digitalWrite(4, 0);
|
||||
return;
|
||||
}
|
||||
DATALEN = PAYLOADLEN - 3;
|
||||
SENDERID = SPI.transfer(0);
|
||||
byte CTLbyte = SPI.transfer(0);
|
||||
|
||||
ACK_RECEIVED = CTLbyte & 0x80; //extract ACK-requested flag
|
||||
ACK_REQUESTED = CTLbyte & 0x40; //extract ACK-received flag
|
||||
|
||||
for (byte i= 0; i < DATALEN; i++)
|
||||
{
|
||||
DATA[i] = SPI.transfer(0);
|
||||
}
|
||||
if (DATALEN<RF69_MAX_DATA_LEN) DATA[DATALEN]=0; //add null at end of string
|
||||
unselect();
|
||||
setMode(RF69_MODE_RX);
|
||||
}
|
||||
RSSI = readRSSI();
|
||||
//digitalWrite(4, 0);
|
||||
}
|
||||
|
||||
void RFM69::isr0() { selfPointer->interruptHandler(); }
|
||||
|
||||
void RFM69::receiveBegin() {
|
||||
DATALEN = 0;
|
||||
SENDERID = 0;
|
||||
TARGETID = 0;
|
||||
PAYLOADLEN = 0;
|
||||
ACK_REQUESTED = 0;
|
||||
ACK_RECEIVED = 0;
|
||||
RSSI = 0;
|
||||
if (readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY)
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFB) | RF_PACKET2_RXRESTART); // avoid RX deadlocks
|
||||
writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01); //set DIO0 to "PAYLOADREADY" in receive mode
|
||||
setMode(RF69_MODE_RX);
|
||||
}
|
||||
|
||||
bool RFM69::receiveDone() {
|
||||
// ATOMIC_BLOCK(ATOMIC_FORCEON)
|
||||
// {
|
||||
noInterrupts(); //re-enabled in unselect() via setMode() or via receiveBegin()
|
||||
if (_mode == RF69_MODE_RX && PAYLOADLEN>0)
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY); //enables interrupts
|
||||
return true;
|
||||
}
|
||||
else if (_mode == RF69_MODE_RX) //already in RX no payload yet
|
||||
{
|
||||
interrupts(); //explicitly re-enable interrupts
|
||||
return false;
|
||||
}
|
||||
receiveBegin();
|
||||
return false;
|
||||
//}
|
||||
}
|
||||
|
||||
// To enable encryption: radio.encrypt("ABCDEFGHIJKLMNOP");
|
||||
// To disable encryption: radio.encrypt(null) or radio.encrypt(0)
|
||||
// KEY HAS TO BE 16 bytes !!!
|
||||
void RFM69::encrypt(const char* key) {
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
if (key!=0)
|
||||
{
|
||||
select();
|
||||
SPI.transfer(REG_AESKEY1 | 0x80);
|
||||
for (byte i = 0; i<16; i++)
|
||||
SPI.transfer(key[i]);
|
||||
unselect();
|
||||
}
|
||||
writeReg(REG_PACKETCONFIG2, (readReg(REG_PACKETCONFIG2) & 0xFE) | (key ? 1 : 0));
|
||||
}
|
||||
|
||||
int RFM69::readRSSI(bool forceTrigger) {
|
||||
int rssi = 0;
|
||||
if (forceTrigger)
|
||||
{
|
||||
//RSSI trigger not needed if DAGC is in continuous mode
|
||||
writeReg(REG_RSSICONFIG, RF_RSSI_START);
|
||||
while ((readReg(REG_RSSICONFIG) & RF_RSSI_DONE) == 0x00); // Wait for RSSI_Ready
|
||||
}
|
||||
rssi = -readReg(REG_RSSIVALUE);
|
||||
rssi >>= 1;
|
||||
return rssi;
|
||||
}
|
||||
|
||||
byte RFM69::readReg(byte addr)
|
||||
{
|
||||
select();
|
||||
SPI.transfer(addr & 0x7F);
|
||||
byte regval = SPI.transfer(0);
|
||||
unselect();
|
||||
return regval;
|
||||
}
|
||||
|
||||
void RFM69::writeReg(byte addr, byte value)
|
||||
{
|
||||
select();
|
||||
SPI.transfer(addr | 0x80);
|
||||
SPI.transfer(value);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// Select the transceiver
|
||||
void RFM69::select() {
|
||||
noInterrupts();
|
||||
//save current SPI settings
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
//set RFM69 SPI settings
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
digitalWrite(_slaveSelectPin, LOW);
|
||||
}
|
||||
|
||||
/// UNselect the transceiver chip
|
||||
void RFM69::unselect() {
|
||||
digitalWrite(_slaveSelectPin, HIGH);
|
||||
//restore SPI settings to what they were before talking to RFM69
|
||||
SPCR = _SPCR;
|
||||
SPSR = _SPSR;
|
||||
interrupts();
|
||||
}
|
||||
|
||||
// ON = disable filtering to capture all frames on network
|
||||
// OFF = enable node+broadcast filtering to capture only frames sent to this/broadcast address
|
||||
void RFM69::promiscuous(bool onOff) {
|
||||
_promiscuousMode=onOff;
|
||||
//writeReg(REG_PACKETCONFIG1, (readReg(REG_PACKETCONFIG1) & 0xF9) | (onOff ? RF_PACKET1_ADRSFILTERING_OFF : RF_PACKET1_ADRSFILTERING_NODEBROADCAST));
|
||||
}
|
||||
|
||||
void RFM69::setHighPower(bool onOff) {
|
||||
_isRFM69HW = onOff;
|
||||
writeReg(REG_OCP, _isRFM69HW ? RF_OCP_OFF : RF_OCP_ON);
|
||||
if (_isRFM69HW) //turning ON
|
||||
writeReg(REG_PALEVEL, (readReg(REG_PALEVEL) & 0x1F) | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON); //enable P1 & P2 amplifier stages
|
||||
else
|
||||
writeReg(REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | _powerLevel); //enable P0 only
|
||||
}
|
||||
|
||||
void RFM69::setHighPowerRegs(bool onOff) {
|
||||
writeReg(REG_TESTPA1, onOff ? 0x5D : 0x55);
|
||||
writeReg(REG_TESTPA2, onOff ? 0x7C : 0x70);
|
||||
}
|
||||
|
||||
void RFM69::setCS(byte newSPISlaveSelect) {
|
||||
_slaveSelectPin = newSPISlaveSelect;
|
||||
pinMode(_slaveSelectPin, OUTPUT);
|
||||
}
|
||||
|
||||
//for debugging
|
||||
void RFM69::readAllRegs()
|
||||
{
|
||||
byte regVal;
|
||||
|
||||
for (byte regAddr = 1; regAddr <= 0x4F; regAddr++)
|
||||
{
|
||||
select();
|
||||
SPI.transfer(regAddr & 0x7f); // send address + r/w bit
|
||||
regVal = SPI.transfer(0);
|
||||
unselect();
|
||||
|
||||
Serial.print(regAddr, HEX);
|
||||
Serial.print(" - ");
|
||||
Serial.print(regVal,HEX);
|
||||
Serial.print(" - ");
|
||||
Serial.println(regVal,BIN);
|
||||
}
|
||||
unselect();
|
||||
}
|
||||
|
||||
byte RFM69::readTemperature(byte calFactor) //returns centigrade
|
||||
{
|
||||
setMode(RF69_MODE_STANDBY);
|
||||
writeReg(REG_TEMP1, RF_TEMP1_MEAS_START);
|
||||
while ((readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING)) Serial.print('*');
|
||||
return ~readReg(REG_TEMP2) + COURSE_TEMP_COEF + calFactor; //'complement'corrects the slope, rising temp = rising val
|
||||
} // COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
|
||||
|
||||
void RFM69::rcCalibration()
|
||||
{
|
||||
writeReg(REG_OSC1, RF_OSC1_RCCAL_START);
|
||||
while ((readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE) == 0x00);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
// **********************************************************************************
|
||||
// Driver definition for HopeRF RFM69W/RFM69HW/RFM69CW/RFM69HCW, Semtech SX1231/1231H
|
||||
// **********************************************************************************
|
||||
// Copyright Felix Rusu (2014), felix@lowpowerlab.com
|
||||
// http://lowpowerlab.com/
|
||||
// **********************************************************************************
|
||||
// License
|
||||
// **********************************************************************************
|
||||
// This program is free software; you can redistribute it
|
||||
// and/or modify it under the terms of the GNU General
|
||||
// Public License as published by the Free Software
|
||||
// Foundation; either version 2 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General
|
||||
// Public License along with this program; if not, write
|
||||
// to the Free Software Foundation, Inc.,
|
||||
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
//
|
||||
// Licence can be viewed at
|
||||
// http://www.fsf.org/licenses/gpl.txt
|
||||
//
|
||||
// Please maintain this license information along with authorship
|
||||
// and copyright notices in any redistribution of this code
|
||||
// **********************************************************************************
|
||||
#ifndef RFM69_h
|
||||
#define RFM69_h
|
||||
#include <Arduino.h> //assumes Arduino IDE v1.0 or greater
|
||||
|
||||
#define RF69_MAX_DATA_LEN 61 // to take advantage of the built in AES/CRC we want to limit the frame size to the internal FIFO size (66 bytes - 3 bytes overhead)
|
||||
#define RF69_SPI_CS SS // SS is the SPI slave select pin, for instance D10 on atmega328
|
||||
|
||||
// INT0 on AVRs should be connected to RFM69's DIO0 (ex on Atmega328 it's D2, on Atmega644/1284 it's D2)
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega88) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega32U4__)
|
||||
#define RF69_IRQ_PIN 2
|
||||
#define RF69_IRQ_NUM 0
|
||||
#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
|
||||
#define RF69_IRQ_PIN 2
|
||||
#define RF69_IRQ_NUM 2
|
||||
#endif
|
||||
|
||||
#define CSMA_LIMIT -90 // upper RX signal sensitivity threshold in dBm for carrier sense access
|
||||
#define RF69_MODE_SLEEP 0 // XTAL OFF
|
||||
#define RF69_MODE_STANDBY 1 // XTAL ON
|
||||
#define RF69_MODE_SYNTH 2 // PLL ON
|
||||
#define RF69_MODE_RX 3 // RX MODE
|
||||
#define RF69_MODE_TX 4 // TX MODE
|
||||
|
||||
//available frequency bands
|
||||
#define RF69_315MHZ 31 // non trivial values to avoid misconfiguration
|
||||
#define RF69_433MHZ 43
|
||||
#define RF69_868MHZ 86
|
||||
#define RF69_915MHZ 91
|
||||
|
||||
#define null 0
|
||||
#define COURSE_TEMP_COEF -90 // puts the temperature reading in the ballpark, user can fine tune the returned value
|
||||
#define RF69_BROADCAST_ADDR 255
|
||||
#define RF69_CSMA_LIMIT_MS 1000
|
||||
|
||||
class RFM69 {
|
||||
public:
|
||||
static volatile byte DATA[RF69_MAX_DATA_LEN]; // recv/xmit buf, including hdr & crc bytes
|
||||
static volatile byte DATALEN;
|
||||
static volatile byte SENDERID;
|
||||
static volatile byte TARGETID; //should match _address
|
||||
static volatile byte PAYLOADLEN;
|
||||
static volatile byte ACK_REQUESTED;
|
||||
static volatile byte ACK_RECEIVED; /// Should be polled immediately after sending a packet with ACK request
|
||||
static volatile int RSSI; //most accurate RSSI during reception (closest to the reception)
|
||||
static volatile byte _mode; //should be protected?
|
||||
|
||||
RFM69(byte slaveSelectPin=RF69_SPI_CS, byte interruptPin=RF69_IRQ_PIN, bool isRFM69HW=false, byte interruptNum=RF69_IRQ_NUM) {
|
||||
_slaveSelectPin = slaveSelectPin;
|
||||
_interruptPin = interruptPin;
|
||||
_interruptNum = interruptNum;
|
||||
_mode = RF69_MODE_STANDBY;
|
||||
_promiscuousMode = false;
|
||||
_powerLevel = 31;
|
||||
_isRFM69HW = isRFM69HW;
|
||||
}
|
||||
|
||||
bool initialize(byte freqBand, byte ID, byte networkID=1);
|
||||
void setAddress(byte addr);
|
||||
bool canSend();
|
||||
void send(byte toAddress, const void* buffer, byte bufferSize, bool requestACK=false);
|
||||
bool sendWithRetry(byte toAddress, const void* buffer, byte bufferSize, byte retries=2, byte retryWaitTime=40); //40ms roundtrip req for 61byte packets
|
||||
bool receiveDone();
|
||||
bool ACKReceived(byte fromNodeID);
|
||||
bool ACKRequested();
|
||||
void sendACK(const void* buffer = "", uint8_t bufferSize=0);
|
||||
void setFrequency(uint32_t FRF);
|
||||
void encrypt(const char* key);
|
||||
void setCS(byte newSPISlaveSelect);
|
||||
int readRSSI(bool forceTrigger=false);
|
||||
void promiscuous(bool onOff=true);
|
||||
void setHighPower(bool onOFF=true); //have to call it after initialize for RFM69HW
|
||||
void setPowerLevel(byte level); //reduce/increase transmit power level
|
||||
void sleep();
|
||||
byte readTemperature(byte calFactor=0); //get CMOS temperature (8bit)
|
||||
void rcCalibration(); //calibrate the internal RC oscillator for use in wide temperature variations - see datasheet section [4.3.5. RC Timer Accuracy]
|
||||
|
||||
// allow hacking registers by making these public
|
||||
byte readReg(byte addr);
|
||||
void writeReg(byte addr, byte val);
|
||||
void readAllRegs();
|
||||
|
||||
protected:
|
||||
static void isr0();
|
||||
void virtual interruptHandler();
|
||||
void sendFrame(byte toAddress, const void* buffer, byte size, bool requestACK=false, bool sendACK=false);
|
||||
|
||||
static RFM69* selfPointer;
|
||||
byte _slaveSelectPin;
|
||||
byte _interruptPin;
|
||||
byte _interruptNum;
|
||||
byte _address;
|
||||
bool _promiscuousMode;
|
||||
byte _powerLevel;
|
||||
bool _isRFM69HW;
|
||||
byte _SPCR;
|
||||
byte _SPSR;
|
||||
|
||||
void receiveBegin();
|
||||
void setMode(byte mode);
|
||||
void setHighPowerRegs(bool onOff);
|
||||
void select();
|
||||
void unselect();
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,293 @@
|
||||
// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com
|
||||
// SPI Flash memory library for arduino/moteino.
|
||||
// This works with 256byte/page SPI flash memory
|
||||
// For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes)
|
||||
// Minimal modifications should allow chips that have different page size but modifications
|
||||
// DEPENDS ON: Arduino SPI library
|
||||
// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
|
||||
// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
||||
// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4
|
||||
// **********************************************************************************
|
||||
// License
|
||||
// **********************************************************************************
|
||||
// This program is free software; you can redistribute it
|
||||
// and/or modify it under the terms of the GNU General
|
||||
// Public License as published by the Free Software
|
||||
// Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General
|
||||
// Public License along with this program.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Licence can be viewed at
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
//
|
||||
// Please maintain this license information along with authorship
|
||||
// and copyright notices in any redistribution of this code
|
||||
|
||||
#include <SPIFlash.h>
|
||||
|
||||
uint8_t SPIFlash::UNIQUEID[8];
|
||||
|
||||
/// IMPORTANT: NAND FLASH memory requires erase before write, because
|
||||
/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s
|
||||
/// See http://en.wikipedia.org/wiki/Flash_memory
|
||||
/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
|
||||
|
||||
/// Constructor. JedecID is optional but recommended, since this will ensure that the device is present and has a valid response
|
||||
/// get this from the datasheet of your flash chip
|
||||
/// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
||||
/// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
|
||||
SPIFlash::SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID) {
|
||||
_slaveSelectPin = slaveSelectPin;
|
||||
_jedecID = jedecID;
|
||||
}
|
||||
|
||||
/// Select the flash chip
|
||||
void SPIFlash::select() {
|
||||
//save current SPI settings
|
||||
#ifndef SPI_HAS_TRANSACTION
|
||||
noInterrupts();
|
||||
#endif
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPI.beginTransaction(_settings);
|
||||
#else
|
||||
// set FLASH SPI settings
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
SPI.setBitOrder(MSBFIRST);
|
||||
SPI.setClockDivider(SPI_CLOCK_DIV4); //decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
|
||||
SPI.begin();
|
||||
#endif
|
||||
digitalWrite(_slaveSelectPin, LOW);
|
||||
}
|
||||
|
||||
/// UNselect the flash chip
|
||||
void SPIFlash::unselect() {
|
||||
digitalWrite(_slaveSelectPin, HIGH);
|
||||
//restore SPI settings to what they were before talking to the FLASH chip
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPI.endTransaction();
|
||||
#else
|
||||
interrupts();
|
||||
#endif
|
||||
SPCR = _SPCR;
|
||||
SPSR = _SPSR;
|
||||
}
|
||||
|
||||
/// setup SPI, read device ID etc...
|
||||
boolean SPIFlash::initialize()
|
||||
{
|
||||
_SPCR = SPCR;
|
||||
_SPSR = SPSR;
|
||||
pinMode(_slaveSelectPin, OUTPUT);
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
|
||||
#endif
|
||||
|
||||
unselect();
|
||||
wakeup();
|
||||
|
||||
if (_jedecID == 0 || readDeviceId() == _jedecID) {
|
||||
command(SPIFLASH_STATUSWRITE, true); // Write Status Register
|
||||
SPI.transfer(0); // Global Unprotect
|
||||
unselect();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Get the manufacturer and device ID bytes (as a short word)
|
||||
uint16_t SPIFlash::readDeviceId()
|
||||
{
|
||||
#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo
|
||||
command(SPIFLASH_IDREAD); // Read JEDEC ID
|
||||
#else
|
||||
select();
|
||||
SPI.transfer(SPIFLASH_IDREAD);
|
||||
#endif
|
||||
uint16_t jedecid = SPI.transfer(0) << 8;
|
||||
jedecid |= SPI.transfer(0);
|
||||
unselect();
|
||||
return jedecid;
|
||||
}
|
||||
|
||||
/// Get the 64 bit unique identifier, stores it in UNIQUEID[8]. Only needs to be called once, ie after initialize
|
||||
/// Returns the byte pointer to the UNIQUEID byte array
|
||||
/// Read UNIQUEID like this:
|
||||
/// flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(flash.UNIQUEID[i], HEX); Serial.print(' '); }
|
||||
/// or like this:
|
||||
/// flash.readUniqueId(); uint8_t* MAC = flash.readUniqueId(); for (uint8_t i=0;i<8;i++) { Serial.print(MAC[i], HEX); Serial.print(' '); }
|
||||
uint8_t* SPIFlash::readUniqueId()
|
||||
{
|
||||
command(SPIFLASH_MACREAD);
|
||||
SPI.transfer(0);
|
||||
SPI.transfer(0);
|
||||
SPI.transfer(0);
|
||||
SPI.transfer(0);
|
||||
for (uint8_t i=0;i<8;i++)
|
||||
UNIQUEID[i] = SPI.transfer(0);
|
||||
unselect();
|
||||
return UNIQUEID;
|
||||
}
|
||||
|
||||
/// read 1 byte from flash memory
|
||||
uint8_t SPIFlash::readByte(uint32_t addr) {
|
||||
command(SPIFLASH_ARRAYREADLOWFREQ);
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
uint8_t result = SPI.transfer(0);
|
||||
unselect();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// read unlimited # of bytes
|
||||
void SPIFlash::readBytes(uint32_t addr, void* buf, uint16_t len) {
|
||||
command(SPIFLASH_ARRAYREAD);
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
SPI.transfer(0); //"dont care"
|
||||
for (uint16_t i = 0; i < len; ++i)
|
||||
((uint8_t*) buf)[i] = SPI.transfer(0);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// Send a command to the flash chip, pass TRUE for isWrite when its a write command
|
||||
void SPIFlash::command(uint8_t cmd, boolean isWrite){
|
||||
#if defined(__AVR_ATmega32U4__) // Arduino Leonardo, MoteinoLeo
|
||||
DDRB |= B00000001; // Make sure the SS pin (PB0 - used by RFM12B on MoteinoLeo R1) is set as output HIGH!
|
||||
PORTB |= B00000001;
|
||||
#endif
|
||||
if (isWrite)
|
||||
{
|
||||
command(SPIFLASH_WRITEENABLE); // Write Enable
|
||||
unselect();
|
||||
}
|
||||
//wait for any write/erase to complete
|
||||
// a time limit cannot really be added here without it being a very large safe limit
|
||||
// that is because some chips can take several seconds to carry out a chip erase or other similar multi block or entire-chip operations
|
||||
// a recommended alternative to such situations where chip can be or not be present is to add a 10k or similar weak pulldown on the
|
||||
// open drain MISO input which can read noise/static and hence return a non 0 status byte, causing the while() to hang when a flash chip is not present
|
||||
while(busy());
|
||||
select();
|
||||
SPI.transfer(cmd);
|
||||
}
|
||||
|
||||
/// check if the chip is busy erasing/writing
|
||||
boolean SPIFlash::busy()
|
||||
{
|
||||
/*
|
||||
select();
|
||||
SPI.transfer(SPIFLASH_STATUSREAD);
|
||||
uint8_t status = SPI.transfer(0);
|
||||
unselect();
|
||||
return status & 1;
|
||||
*/
|
||||
return readStatus() & 1;
|
||||
}
|
||||
|
||||
/// return the STATUS register
|
||||
uint8_t SPIFlash::readStatus()
|
||||
{
|
||||
select();
|
||||
SPI.transfer(SPIFLASH_STATUSREAD);
|
||||
uint8_t status = SPI.transfer(0);
|
||||
unselect();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/// Write 1 byte to flash memory
|
||||
/// WARNING: you can only write to previously erased memory locations (see datasheet)
|
||||
/// use the block erase commands to first clear memory (write 0xFFs)
|
||||
void SPIFlash::writeByte(uint32_t addr, uint8_t byt) {
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
SPI.transfer(byt);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// write multiple bytes to flash memory (up to 64K)
|
||||
/// WARNING: you can only write to previously erased memory locations (see datasheet)
|
||||
/// use the block erase commands to first clear memory (write 0xFFs)
|
||||
/// This version handles both page alignment and data blocks larger than 256 bytes.
|
||||
///
|
||||
void SPIFlash::writeBytes(uint32_t addr, const void* buf, uint16_t len) {
|
||||
uint16_t n;
|
||||
uint16_t maxBytes = 256-(addr%256); // force the first set of bytes to stay within the first page
|
||||
uint16_t offset = 0;
|
||||
while (len>0)
|
||||
{
|
||||
n = (len<=maxBytes) ? len : maxBytes;
|
||||
command(SPIFLASH_BYTEPAGEPROGRAM, true); // Byte/Page Program
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
|
||||
for (uint16_t i = 0; i < n; i++)
|
||||
SPI.transfer(((uint8_t*) buf)[offset + i]);
|
||||
unselect();
|
||||
|
||||
addr+=n; // adjust the addresses and remaining bytes by what we've just transferred.
|
||||
offset +=n;
|
||||
len -= n;
|
||||
maxBytes = 256; // now we can do up to 256 bytes per loop
|
||||
}
|
||||
}
|
||||
|
||||
/// erase entire flash memory array
|
||||
/// may take several seconds depending on size, but is non blocking
|
||||
/// so you may wait for this to complete using busy() or continue doing
|
||||
/// other things and later check if the chip is done with busy()
|
||||
/// note that any command will first wait for chip to become available using busy()
|
||||
/// so no need to do that twice
|
||||
void SPIFlash::chipErase() {
|
||||
command(SPIFLASH_CHIPERASE, true);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// erase a 4Kbyte block
|
||||
void SPIFlash::blockErase4K(uint32_t addr) {
|
||||
command(SPIFLASH_BLOCKERASE_4K, true); // Block Erase
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// erase a 32Kbyte block
|
||||
void SPIFlash::blockErase32K(uint32_t addr) {
|
||||
command(SPIFLASH_BLOCKERASE_32K, true); // Block Erase
|
||||
SPI.transfer(addr >> 16);
|
||||
SPI.transfer(addr >> 8);
|
||||
SPI.transfer(addr);
|
||||
unselect();
|
||||
}
|
||||
|
||||
void SPIFlash::sleep() {
|
||||
command(SPIFLASH_SLEEP);
|
||||
unselect();
|
||||
}
|
||||
|
||||
void SPIFlash::wakeup() {
|
||||
command(SPIFLASH_WAKE);
|
||||
unselect();
|
||||
}
|
||||
|
||||
/// cleanup
|
||||
void SPIFlash::end() {
|
||||
SPI.end();
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2013-2015 by Felix Rusu, LowPowerLab.com
|
||||
// SPI Flash memory library for arduino/moteino.
|
||||
// This works with 256byte/page SPI flash memory
|
||||
// For instance a 4MBit (512Kbyte) flash chip will have 2048 pages: 256*2048 = 524288 bytes (512Kbytes)
|
||||
// Minimal modifications should allow chips that have different page size but modifications
|
||||
// DEPENDS ON: Arduino SPI library
|
||||
// > Updated Jan. 5, 2015, TomWS1, modified writeBytes to allow blocks > 256 bytes and handle page misalignment.
|
||||
// > Updated Feb. 26, 2015 TomWS1, added support for SPI Transactions (Arduino 1.5.8 and above)
|
||||
// > Selective merge by Felix after testing in IDE 1.0.6, 1.6.4
|
||||
// **********************************************************************************
|
||||
// License
|
||||
// **********************************************************************************
|
||||
// This program is free software; you can redistribute it
|
||||
// and/or modify it under the terms of the GNU General
|
||||
// Public License as published by the Free Software
|
||||
// Foundation; either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will
|
||||
// be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
// implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
// PARTICULAR PURPOSE. See the GNU General Public
|
||||
// License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General
|
||||
// Public License along with this program.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
// Licence can be viewed at
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
//
|
||||
// Please maintain this license information along with authorship
|
||||
// and copyright notices in any redistribution of this code
|
||||
|
||||
#ifndef _SPIFLASH_H_
|
||||
#define _SPIFLASH_H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <wiring.h>
|
||||
#include "pins_arduino.h"
|
||||
#endif
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
/// IMPORTANT: NAND FLASH memory requires erase before write, because
|
||||
/// it can only transition from 1s to 0s and only the erase command can reset all 0s to 1s
|
||||
/// See http://en.wikipedia.org/wiki/Flash_memory
|
||||
/// The smallest range that can be erased is a sector (4K, 32K, 64K); there is also a chip erase command
|
||||
|
||||
/// Standard SPI flash commands
|
||||
/// Assuming the WP pin is pulled up (to disable hardware write protection)
|
||||
/// To use any write commands the WEL bit in the status register must be set to 1.
|
||||
/// This is accomplished by sending a 0x06 command before any such write/erase command.
|
||||
/// The WEL bit in the status register resets to the logical ?0? state after a
|
||||
/// device power-up or reset. In addition, the WEL bit will be reset to the logical ?0? state automatically under the following conditions:
|
||||
/// ? Write Disable operation completes successfully
|
||||
/// ? Write Status Register operation completes successfully or aborts
|
||||
/// ? Protect Sector operation completes successfully or aborts
|
||||
/// ? Unprotect Sector operation completes successfully or aborts
|
||||
/// ? Byte/Page Program operation completes successfully or aborts
|
||||
/// ? Sequential Program Mode reaches highest unprotected memory location
|
||||
/// ? Sequential Program Mode reaches the end of the memory array
|
||||
/// ? Sequential Program Mode aborts
|
||||
/// ? Block Erase operation completes successfully or aborts
|
||||
/// ? Chip Erase operation completes successfully or aborts
|
||||
/// ? Hold condition aborts
|
||||
#define SPIFLASH_WRITEENABLE 0x06 // write enable
|
||||
#define SPIFLASH_WRITEDISABLE 0x04 // write disable
|
||||
|
||||
#define SPIFLASH_BLOCKERASE_4K 0x20 // erase one 4K block of flash memory
|
||||
#define SPIFLASH_BLOCKERASE_32K 0x52 // erase one 32K block of flash memory
|
||||
#define SPIFLASH_BLOCKERASE_64K 0xD8 // erase one 64K block of flash memory
|
||||
#define SPIFLASH_CHIPERASE 0x60 // chip erase (may take several seconds depending on size)
|
||||
// but no actual need to wait for completion (instead need to check the status register BUSY bit)
|
||||
#define SPIFLASH_STATUSREAD 0x05 // read status register
|
||||
#define SPIFLASH_STATUSWRITE 0x01 // write status register
|
||||
#define SPIFLASH_ARRAYREAD 0x0B // read array (fast, need to add 1 dummy byte after 3 address bytes)
|
||||
#define SPIFLASH_ARRAYREADLOWFREQ 0x03 // read array (low frequency)
|
||||
|
||||
#define SPIFLASH_SLEEP 0xB9 // deep power down
|
||||
#define SPIFLASH_WAKE 0xAB // deep power wake up
|
||||
#define SPIFLASH_BYTEPAGEPROGRAM 0x02 // write (1 to 256bytes)
|
||||
#define SPIFLASH_IDREAD 0x9F // read JEDEC manufacturer and device ID (2 bytes, specific bytes for each manufacturer and device)
|
||||
// Example for Atmel-Adesto 4Mbit AT25DF041A: 0x1F44 (page 27: http://www.adestotech.com/sites/default/files/datasheets/doc3668.pdf)
|
||||
// Example for Winbond 4Mbit W25X40CL: 0xEF30 (page 14: http://www.winbond.com/NR/rdonlyres/6E25084C-0BFE-4B25-903D-AE10221A0929/0/W25X40CL.pdf)
|
||||
#define SPIFLASH_MACREAD 0x4B // read unique ID number (MAC)
|
||||
|
||||
class SPIFlash {
|
||||
public:
|
||||
static uint8_t UNIQUEID[8];
|
||||
SPIFlash(uint8_t slaveSelectPin, uint16_t jedecID=0);
|
||||
boolean initialize();
|
||||
void command(uint8_t cmd, boolean isWrite=false);
|
||||
uint8_t readStatus();
|
||||
uint8_t readByte(uint32_t addr);
|
||||
void readBytes(uint32_t addr, void* buf, uint16_t len);
|
||||
void writeByte(uint32_t addr, uint8_t byt);
|
||||
void writeBytes(uint32_t addr, const void* buf, uint16_t len);
|
||||
boolean busy();
|
||||
void chipErase();
|
||||
void blockErase4K(uint32_t address);
|
||||
void blockErase32K(uint32_t address);
|
||||
uint16_t readDeviceId();
|
||||
uint8_t* readUniqueId();
|
||||
|
||||
void sleep();
|
||||
void wakeup();
|
||||
void end();
|
||||
protected:
|
||||
void select();
|
||||
void unselect();
|
||||
uint8_t _slaveSelectPin;
|
||||
uint16_t _jedecID;
|
||||
uint8_t _SPCR;
|
||||
uint8_t _SPSR;
|
||||
#ifdef SPI_HAS_TRANSACTION
|
||||
SPISettings _settings;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
#include <string.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "sha256.h"
|
||||
|
||||
|
||||
const uint32_t sha256K[] PROGMEM = {
|
||||
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
|
||||
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
|
||||
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
|
||||
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
|
||||
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
|
||||
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
|
||||
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
|
||||
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
|
||||
};
|
||||
|
||||
#define BUFFER_SIZE 64
|
||||
|
||||
const uint8_t sha256InitState[] PROGMEM = {
|
||||
0x67,0xe6,0x09,0x6a, // H0
|
||||
0x85,0xae,0x67,0xbb, // H1
|
||||
0x72,0xf3,0x6e,0x3c, // H2
|
||||
0x3a,0xf5,0x4f,0xa5, // H3
|
||||
0x7f,0x52,0x0e,0x51, // H4
|
||||
0x8c,0x68,0x05,0x9b, // H5
|
||||
0xab,0xd9,0x83,0x1f, // H6
|
||||
0x19,0xcd,0xe0,0x5b // H7
|
||||
};
|
||||
|
||||
void Sha256Class::init(void) {
|
||||
memcpy_P(state.b,sha256InitState,32);
|
||||
byteCount = 0;
|
||||
bufferOffset = 0;
|
||||
}
|
||||
|
||||
uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) {
|
||||
return ((number << (32-bits)) | (number >> bits));
|
||||
}
|
||||
|
||||
void Sha256Class::hashBlock() {
|
||||
uint8_t i;
|
||||
uint32_t a,b,c,d,e,f,g,h,t1,t2;
|
||||
|
||||
a=state.w[0];
|
||||
b=state.w[1];
|
||||
c=state.w[2];
|
||||
d=state.w[3];
|
||||
e=state.w[4];
|
||||
f=state.w[5];
|
||||
g=state.w[6];
|
||||
h=state.w[7];
|
||||
|
||||
for (i=0; i<64; i++) {
|
||||
if (i>=16) {
|
||||
t1 = buffer.w[i&15] + buffer.w[(i-7)&15];
|
||||
t2 = buffer.w[(i-2)&15];
|
||||
t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10);
|
||||
t2 = buffer.w[(i-15)&15];
|
||||
t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3);
|
||||
buffer.w[i&15] = t1;
|
||||
}
|
||||
t1 = h;
|
||||
t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e)
|
||||
t1 += g ^ (e & (g ^ f)); // Ch(e,f,g)
|
||||
t1 += pgm_read_dword(sha256K+i); // Ki
|
||||
t1 += buffer.w[i&15]; // Wi
|
||||
t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a)
|
||||
t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c)
|
||||
h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2;
|
||||
}
|
||||
state.w[0] += a;
|
||||
state.w[1] += b;
|
||||
state.w[2] += c;
|
||||
state.w[3] += d;
|
||||
state.w[4] += e;
|
||||
state.w[5] += f;
|
||||
state.w[6] += g;
|
||||
state.w[7] += h;
|
||||
}
|
||||
|
||||
void Sha256Class::addUncounted(uint8_t data) {
|
||||
buffer.b[bufferOffset ^ 3] = data;
|
||||
bufferOffset++;
|
||||
if (bufferOffset == BUFFER_SIZE) {
|
||||
hashBlock();
|
||||
bufferOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Sha256Class::write(uint8_t data) {
|
||||
++byteCount;
|
||||
addUncounted(data);
|
||||
}
|
||||
|
||||
void Sha256Class::pad() {
|
||||
// Implement SHA-256 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
addUncounted(0x80);
|
||||
while (bufferOffset != 56) addUncounted(0x00);
|
||||
|
||||
// Append length in the last 8 bytes
|
||||
addUncounted(0); // We're only using 32 bit lengths
|
||||
addUncounted(0); // But SHA-1 supports 64 bit lengths
|
||||
addUncounted(0); // So zero pad the top bits
|
||||
addUncounted(byteCount >> 29); // Shifting to multiply by 8
|
||||
addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||
addUncounted(byteCount >> 13); // byte.
|
||||
addUncounted(byteCount >> 5);
|
||||
addUncounted(byteCount << 3);
|
||||
}
|
||||
|
||||
|
||||
uint8_t* Sha256Class::result(void) {
|
||||
// Pad to complete the last block
|
||||
pad();
|
||||
|
||||
// Swap byte order back
|
||||
for (int i=0; i<8; i++) {
|
||||
uint32_t a,b;
|
||||
a=state.w[i];
|
||||
b=a<<24;
|
||||
b|=(a<<8) & 0x00ff0000;
|
||||
b|=(a>>8) & 0x0000ff00;
|
||||
b|=a>>24;
|
||||
state.w[i]=b;
|
||||
}
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
return state.b;
|
||||
}
|
||||
|
||||
#define HMAC_IPAD 0x36
|
||||
#define HMAC_OPAD 0x5c
|
||||
|
||||
uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a
|
||||
uint8_t innerHash[HASH_LENGTH];
|
||||
|
||||
void Sha256Class::initHmac(const uint8_t* key, int keyLength) {
|
||||
uint8_t i;
|
||||
memset(keyBuffer,0,BLOCK_LENGTH);
|
||||
if (keyLength > BLOCK_LENGTH) {
|
||||
// Hash long keys
|
||||
init();
|
||||
for (;keyLength--;) write(*key++);
|
||||
memcpy(keyBuffer,result(),HASH_LENGTH);
|
||||
} else {
|
||||
// Block length keys are used as is
|
||||
memcpy(keyBuffer,key,keyLength);
|
||||
}
|
||||
// Start inner hash
|
||||
init();
|
||||
for (i=0; i<BLOCK_LENGTH; i++) {
|
||||
write(keyBuffer[i] ^ HMAC_IPAD);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* Sha256Class::resultHmac(void) {
|
||||
uint8_t i;
|
||||
// Complete inner hash
|
||||
memcpy(innerHash,result(),HASH_LENGTH);
|
||||
// Calculate outer hash
|
||||
init();
|
||||
for (i=0; i<BLOCK_LENGTH; i++) write(keyBuffer[i] ^ HMAC_OPAD);
|
||||
for (i=0; i<HASH_LENGTH; i++) write(innerHash[i]);
|
||||
return result();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user