-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAkeru.cpp
180 lines (147 loc) · 4.1 KB
/
Akeru.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// Akeru library - http://akeru.cc
//
// copyleft Snootlab, 2014
// this code is public domain, enjoy!
#include <Arduino.h>
#include "Akeru.h"
Akeru_ Akeru;
Akeru_::Akeru_() :
_serial(5, 4) {
//Since _lastSend is unsigned, this is infinity
_lastSend = -1;
}
Akeru_::~Akeru_() {
}
void Akeru_::begin() {
_serial.begin(9600);
//Remove un-ended commands from TST's buffer
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)';');
//Wait for the "KO;"
while(_serial.available() < 3);
_serial.read(); //'K'
_serial.read(); //'O'
_serial.read(); //';'
}
bool Akeru_::isReady() {
// IMPORTANT WARNING. PLEASE READ BEFORE MODIFYING THE CODE
//
// The Sigfox network operates on public frequencies. To comply with
// radio regulation, it can send radio data a maximum of 1% of the time
// to leave room to other devices using the same frequencies.
//
// Sending a message takes about 6 seconds (it's sent 3 times for
// redundancy purposes), meaning the interval between messages should
// be 10 minutes.
//
// Also make sure your send rate complies with the restrictions set
// by the particular subscription contract you have with your Sigfox
// network operator.
//
// FAILING TO COMPLY WITH THESE CONSTRAINTS MAY CAUSE YOUR MODEM
// TO BE BLOCKED BY YOUR SIFGOX NETWORK OPERATOR.
//
// You've been warned!
unsigned long currentTime = millis();
if(currentTime >= _lastSend && (currentTime - _lastSend) <= 600000) {
return false;
}
// Time is ok, ask the modem's status
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)'S');
_serial.write((uint8_t)'F');
_serial.write((uint8_t)'P');
_serial.write((uint8_t)';');
return _nextReturn() == OK;
}
bool Akeru_::send(const void* data, uint8_t len) {
uint8_t* bytes = (uint8_t*)data;
_serial.listen();
if(!isReady()) {
return false;
}
// See comment in isReady()
_lastSend = millis();
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)'S');
_serial.write((uint8_t)'F');
_serial.write((uint8_t)'M');
_serial.write(len);
for(uint8_t i = 0; i < len; ++i) {
_serial.write(bytes[i]);
}
_serial.write(';');
uint8_t ok = _nextReturn();
if(ok == OK) {
_nextReturn(); //SENT
return true;
}
return false;
}
uint8_t Akeru_::getRev() {
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)'S');
_serial.write((uint8_t)'F');
_serial.write((uint8_t)'v');
_serial.write((uint8_t)';');
while(_serial.available()<3);
if(_serial.peek() == 'K') {
_serial.read(); //'K'
_serial.read(); //'O'
_serial.read(); //';'
return 0;
} else {
while(_serial.available()<5);
uint8_t rev = 10 * (_serial.read() - '0') + (_serial.read() - '0');
_serial.read(); //'O'
_serial.read(); //'K'
_serial.read(); //';'
return rev;
}
}
unsigned long Akeru_::getID() {
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)'S');
_serial.write((uint8_t)'F');
_serial.write((uint8_t)'I');
_serial.write((uint8_t)'D');
_serial.write((uint8_t)';');
//Response is [byte1, byte2, ..., byteN, 'O', 'K']
uint8_t response[8] = {0};
uint8_t i = 0;
while(!_serial.available());
while(_serial.peek() != ';') {
response[i] = _serial.read();
while(!_serial.available());
++i;
}
_serial.read(); //';'
unsigned long id = 0;
for(uint8_t j = 0; j < i-2; ++j) {
id += response[j] << ((i-3-j) * 8);
}
return id;
}
//Power value:
//0 -25 -30 dBm
//1 0dBm
//2 14dBm
//3 16dBm
//4 18dBm
//5 Max (18-19dBm)
bool Akeru_::setPower(uint8_t power) {
power = power % 6; //It's 0-5
_serial.write((uint8_t)'\0');
_serial.write((uint8_t)'S');
_serial.write((uint8_t)'F');
_serial.write((uint8_t)'G');
_serial.write(power);
_serial.write((uint8_t)';');
return _nextReturn() == OK;
}
uint8_t Akeru_::_nextReturn() {
while(!_serial.available());
char fstChar = _serial.read();
while(_serial.read() != ';');
return fstChar;
}