Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Thomas Mørch
2015-07-30 22:36:12 +02:00
112 changed files with 12848 additions and 2878 deletions
+2 -1
View File
@@ -1,2 +1,3 @@
stino.settings
*~
*bak
*bak
+8 -2
View File
@@ -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
View File
@@ -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
+3 -2
View File
@@ -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");
+3
View File
@@ -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 -1
View File
@@ -1,6 +1,6 @@
Arduino
=======
MySensors Arduino Library v1.4
MySensors Arduino Library v1.5
Please visit www.mysensors.org for more information
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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()
{
}
+4
View File
@@ -0,0 +1,4 @@
MsTimer2 KEYWORD1
set KEYWORD2
start KEYWORD2
stop KEYWORD2
+137 -17
View File
@@ -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
-312
View File
@@ -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; }
}
-72
View File
@@ -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
+23
View File
@@ -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() {
}
+54
View File
@@ -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
+211
View File
@@ -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
+90
View File
@@ -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
-354
View File
@@ -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; }
}
-83
View File
@@ -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
+20
View File
@@ -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>
+30 -17
View File
@@ -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.
+23
View File
@@ -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() {
}
+35
View File
@@ -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
+101
View File
@@ -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;
}
+34
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+162 -67
View File
@@ -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
+28
View File
@@ -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;
}
+87
View File
@@ -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
+266
View File
@@ -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(&current_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(&current_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(&current_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(&current_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];
}
+77
View File
@@ -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(&current_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
+91
View File
@@ -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;
}
+53
View File
@@ -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
+23
View File
@@ -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() {
}
+65
View File
@@ -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
+92
View File
@@ -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();
}
+52
View File
@@ -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
+73
View File
@@ -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();
}
+48
View File
@@ -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
+2 -2
View File
@@ -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>
@@ -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>
@@ -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>
@@ -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>
+573
View File
@@ -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;
}
+247
View File
@@ -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
-856
View File
@@ -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;
-137
View File
@@ -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
View File
View File
+5 -4
View File
@@ -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
+464
View File
@@ -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);
}
+136
View File
@@ -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
+293
View File
@@ -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();
}
+123
View File
@@ -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
+168
View File
@@ -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