Created
September 30, 2017 18:56
-
-
Save ntoto/37ffea8a4efefaf2ab4a49edbbac6472 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <SoftwareSerial.h> | |
SoftwareSerial BTserial(8,9); | |
//#define BTserial Serial1 | |
#define HEADER1 0xef | |
#define HEADER2 0xdd | |
unsigned long lastHeartbeat = 0; | |
class Event { | |
unsigned char type = 0; | |
float value = 0; | |
public: | |
Event(unsigned char *payload, size_t len) { | |
unsigned char type =0; | |
float value = 0; | |
unsigned char unit = 0; | |
if (len < 1) { | |
return; | |
} | |
type = payload[0]; | |
// weight | |
if (type == 5) { | |
if (len < 7) { | |
return; | |
} | |
value = ((payload[2] & 0xff) << 8) + (payload[1] & 0xff); | |
unit = payload[5] & 0xFF; | |
if (unit == 1) { | |
value /= 10; | |
} | |
else if (unit == 2) { | |
value /= 100; | |
} | |
else if (unit == 3) { | |
value /= 1000; | |
} | |
else if (unit == 4) { | |
value /= 10000; | |
} | |
if ((payload[6] & 0x02) == 0x02) { | |
value *= -1; | |
} | |
this->value = value; | |
} | |
this->type = type; | |
} | |
unsigned char getType() { | |
return this->type; | |
} | |
float getValue() { | |
return this->value; | |
} | |
}; | |
class Message { | |
unsigned char type; | |
unsigned char *payload = NULL; | |
size_t len = 0; | |
Event * event = NULL; | |
public: | |
Message(unsigned char type, unsigned char *payload, size_t len) { | |
this->type = type; | |
this->payload = payload; | |
this->len = len; | |
if (this->type == 12) { | |
event = new Event(payload, len); | |
} | |
} | |
~Message() { | |
if (payload != NULL) { | |
free(payload); | |
} | |
} | |
unsigned char getType() { | |
return this->type; | |
} | |
unsigned char * getPayload() { | |
return this->payload; | |
} | |
Event * getEvent() { | |
return this->event; | |
} | |
}; | |
void setup() | |
{ | |
Serial.begin(9600); | |
BTserial.begin(9600); | |
Serial.println("BTserial started at 9600"); | |
BTserial.print("AT+IMME1" ); | |
delay(1000); | |
BTserial.print("AT+MODE2" ); | |
delay(1000); | |
BTserial.print("AT+COMP1" ); | |
delay(1000); | |
BTserial.print("AT+UUID0x1800" ); | |
delay(1000); | |
BTserial.print("AT+CHAR0x2A80" ); | |
delay(1000); | |
BTserial.print("AT+ROLE1" ); | |
delay(1000); | |
BTserial.print("AT+CO0001C9714F68E" ); | |
delay(1000); | |
sendId(); | |
delay(1000); | |
sendNotificationRequest(); | |
delay(1000); | |
lastHeartbeat = millis(); | |
} | |
void sendMessage(char msgType, const unsigned char *payload, size_t len) { | |
unsigned char *bytes = (unsigned char *)malloc(5 + len); | |
unsigned char cksum1 = 0; | |
unsigned char cksum2 = 0; | |
int i; | |
bytes[0] = HEADER1; | |
bytes[1] = HEADER2; | |
bytes[2] = msgType; | |
for (i = 0; i < len; i++) { | |
unsigned char val = payload[i] & 0xff; | |
bytes[3+i] = val; | |
if (i % 2 == 0) { | |
cksum1 += val; | |
} | |
else { | |
cksum2 += val; | |
} | |
} | |
bytes[len + 3] = (cksum1 & 0xFF); | |
bytes[len + 4] = (cksum2 & 0xFF); | |
for (i = 0; i < len + 5; i++) { | |
BTserial.write(bytes[i]); | |
} | |
free(bytes); | |
} | |
void sendHeartbeat() { | |
unsigned long now = millis(); | |
if (lastHeartbeat + 4000 > now) { | |
return; | |
} | |
unsigned char payload[] = {0x02,0x00}; | |
sendMessage(0, payload, sizeof(payload)); | |
lastHeartbeat = now; | |
} | |
void sendId() { | |
unsigned char payload[] = {0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d,0x2d}; | |
sendMessage(11, payload, sizeof(payload)); | |
} | |
void sendTare() { | |
unsigned char payload[] = {0x00}; | |
sendMessage(4, payload, sizeof(payload)); | |
} | |
void sendEvent(unsigned char *payload, size_t len) { | |
unsigned int i; | |
unsigned char *bytes = (unsigned char*)malloc(len + 1); | |
bytes[0] = len + 1; | |
for (i = 0; i < len; i++) { | |
bytes[i+1] = payload[i] & 0xff; | |
} | |
sendMessage(12, bytes, len+1); | |
free(bytes); | |
} | |
void sendNotificationRequest() { | |
unsigned char payload[] = { | |
0, // weight | |
1, // weight argument | |
1, // battery | |
2, // battery argument | |
2, // timer | |
5, // timer argument | |
3, // key | |
4 // setting | |
}; | |
sendEvent(payload, sizeof(payload)); | |
} | |
int readChar(char * c) { | |
// TODO: stop doing that!!!! | |
while (!BTserial.available()) { | |
delay(10); | |
} | |
*c = BTserial.read(); | |
return 0; | |
} | |
int readBytes(unsigned char * buffer, size_t len) { | |
int i; | |
unsigned char c; | |
for (i = 0; i < len; i++) { | |
if (readChar(&c) < 0) { | |
return i; | |
} | |
buffer[i] = c; | |
} | |
return i; | |
} | |
int readHeader(unsigned char *msgType) { | |
unsigned char header[3]; | |
// TODO: deal with AT commands | |
do { | |
if (readChar(header) < 0) { | |
return -1; | |
} | |
} while(header[0] != HEADER1); | |
if (readBytes(header+1, 2) != 2) { | |
return -1; | |
} | |
if (header[0] != HEADER1 || header[1] != HEADER2) { | |
Serial.print("Invalid header received: "); | |
for (int i = 0; i < 3; i++) { | |
char buf[10]; | |
snprintf(buf, sizeof(buf), "%.2X", header[i]); | |
Serial.print(buf); | |
} | |
Serial.println(""); | |
return -1; | |
} | |
*msgType = header[2]; | |
return 0; | |
} | |
Message * readMessage() { | |
unsigned char msgType; | |
unsigned char len; | |
unsigned char *payload; | |
unsigned char cksum[2]; | |
int i; | |
// nothing to read | |
if (!BTserial.available()) { | |
return NULL; | |
} | |
if (readHeader(&msgType) < 0) { | |
Serial.println("Failed to receive message header"); | |
return NULL; | |
} | |
if (msgType == 8 || msgType == 12) { | |
if (readChar(&len) < 0) { | |
Serial.println("Failed to receive message data length"); | |
return NULL; | |
} | |
len--; | |
} | |
else { | |
switch(msgType) { | |
case 0: | |
len = 2; | |
break; | |
default: | |
len = 0; | |
} | |
} | |
payload = (unsigned char*)malloc(len); | |
if (readBytes(payload, len) < 0) { | |
Serial.println("Failed to receive message data"); | |
return NULL; | |
} | |
if (readBytes(cksum, 2) < 0) { | |
Serial.println("Failed to receive message checksum"); | |
return NULL; | |
} | |
// TODO: verify checksum | |
return new Message(msgType, payload, len); | |
} | |
void loop() { | |
sendHeartbeat(); | |
Message *msg = readMessage(); | |
if (msg != NULL) { | |
Serial.print("received message "); | |
Serial.println(msg->getType()); | |
// event | |
if (msg->getType() == 12) { | |
Event *event = msg->getEvent(); | |
// weight | |
if (event->getType() == 5) { | |
Serial.print("weight: "); | |
Serial.println(event->getValue()); | |
} | |
} | |
} | |
delay(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment