Skip to content

Instantly share code, notes, and snippets.

@ntoto
Created September 30, 2017 18:56
Show Gist options
  • Save ntoto/37ffea8a4efefaf2ab4a49edbbac6472 to your computer and use it in GitHub Desktop.
Save ntoto/37ffea8a4efefaf2ab4a49edbbac6472 to your computer and use it in GitHub Desktop.
#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