Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
BernardoCovas committed Mar 28, 2019
0 parents commit 0bd0c5b
Show file tree
Hide file tree
Showing 11 changed files with 533 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# ide folders
.vscode
.vs

# build
build
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.10)

file(GLOB __CC_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

add_library(libninebot ${__CC_SRCS})
70 changes: 70 additions & 0 deletions src/NinebotMessageDefinitions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include <memory.h>
#include <stdio.h>

#include "NinebotMessageDefinitions.hpp"
#include "NinebotMessageUtils.hpp"

NinebotMessage::NinebotMessage(uint8_t *buf)
{
if (memcmp(buf, (const uint8_t []) NINEBOT_PACKET_HEADER, 2) == 0)
buf += 2; /* drop packet header */

uint8_t *payloadStart = buf + NINEBOT_MESSAGE_HEADER_LEN;
memcpy(&_msgHeader, buf, NINEBOT_MESSAGE_HEADER_LEN);
uint8_t *ckStart = payloadStart + _msgHeader.payloadLen;
_payload.assign(payloadStart, ckStart);

}

NinebotMessage::NinebotMessage(NinebotMessageHeader_t *hdr, uint8_t *payload)
{
_msgHeader = *hdr;
_payload.assign(payload, payload + hdr->payloadLen);
};

NinebotMessageHeader_t NinebotMessage::getHeader(void)
{
return _msgHeader;
}

std::vector<uint8_t> NinebotMessage::getPayload(void)
{
return _payload;
}

NinebotMessageCkSum_t NinebotMessage::getCkSum(void)
{
int bufLen = NINEBOT_MESSAGE_HEADER_LEN + _payload.size();
uint8_t buf[bufLen];

/* useful pointers */
uint8_t *headerStart = buf;
uint8_t *payloadStart = headerStart + NINEBOT_MESSAGE_HEADER_LEN;

memcpy(headerStart, &_msgHeader, sizeof(_msgHeader));
memcpy(payloadStart, _payload.data(), _payload.size());

return NinebotMessageCheckSum(buf, bufLen);
}

std::vector<uint8_t> NinebotMessage::serialize(void)
{
NinebotMessageCkSum_t cks = getCkSum();

int bufSize = 2 + NINEBOT_MESSAGE_HEADER_LEN + _payload.size() + 2;
uint8_t buf[bufSize] = NINEBOT_PACKET_HEADER;

/* useful pointers */
uint8_t *headerStart = buf + 2;
uint8_t *payloadStart = headerStart + NINEBOT_MESSAGE_HEADER_LEN;
uint8_t *ckStart = payloadStart + _payload.size();

memcpy(headerStart, &_msgHeader, sizeof(_msgHeader));
memcpy(payloadStart, _payload.data(), _payload.size());
memcpy(ckStart, &cks, 2);

std::vector<uint8_t> _buf;
_buf.assign(buf, buf + bufSize);

return _buf;
}
130 changes: 130 additions & 0 deletions src/NinebotMessageDefinitions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
#pragma once

#include <vector>

#include "NinebotMessageUtils.hpp"

#define NINEBOT_SERIAL_DEFAULT_BAUD 115200
#define NINEBOT_PACKET_HEADER {0x5A, 0xA5} // instead of 0x55 0xAA
#define NINEBOT_MESSAGE_HEADER_LEN 5

/* TODO: (bcovas) Unknown values */
typedef enum
{
NINEBOT_ADDR_ANY,
NINEBOT_ADDR_ESC = 0x20,
NINEBOT_ADDR_BLE = 0x21,
NINEBOT_ADDR_BMS1 = 0x22,
NINEBOT_ADDR_BMS2 = 0x23,
NINEBOT_ADDR_APP1 = 0x3D,
NINEBOT_ADDR_APP2 = 0x3E,
NINEBOT_ADDR_APP3 = 0x3F
}
NinebotDeviceAddr_t;

typedef enum
{
NINEBOT_ESC_COMMAND_REGREAD = 0x01,
NINEBOT_ESC_COMMAND_REGWRITE = 0x02,
NINEBOT_ESC_COMMAND_REGWRITE_NO_RESP = 0x03,
NINEBOT_ESC_COMMAND_START_FIRMWARE_UPDATE = 0x07,
NINEBOT_ESC_COMMAND_WRITE_FIRMWARE_UPDATE = 0x08,
NINEBOT_ESC_COMMAND_FINISH_FIRMWARE_UPDATE = 0x09,
NINEBOT_ESC_COMMAND_USER_RESET = 0x5A,
NINEBOT_ESC_COMMAND_SET_ODOMETER = 0x5C,
NINEBOT_ESC_COMMAND_REGREAD_UPDATE_HEAD_INPUTS = 0x61,
NINEBOT_ESC_COMMAND_UPDATE_HEAD_INPUTS = 0x64,
NINEBOT_ESC_COMMAND_UPDATE_HEAD_INPUTS_NOANS = 0x65,
}
NinebotEscCommand_t;

typedef enum
{
NINEBOT_ESC_REG_MAGIC = 0x00, /* 0x515C ? */
NINEBOT_ESC_REG_MOTOR_PHASE_A_CURRENT = 0x0D,
NINEBOT_ESC_REG_MOTOR_PHASE_B_CURRENT = 0x0E,
NINEBOT_ESC_REG_MOTOR_PHASE_C_CURRENT = 0x0F,
NINEBOT_ESC_REG_ESC_SERIAL = 0x10,
NINEBOT_ESC_REG_SCOOTER_PIN = 0x17,
NINEBOT_ESC_REG_ESC_FIRMWARE_V = 0x1A,
NINEBOT_ESC_REG_ERROR_CODE = 0x1B,
NINEBOT_ESC_REG_WARNING_CODE = 0x1C,
NINEBOT_ESC_REG_ESC_STATUS = 0x1C,
NINEBOT_ESC_REG_BATTERY_LEVEL = 0x22,
NINEBOT_ESC_REG_REMAINING_MILAGE__ = 0x24, /* ? */
NINEBOT_ESC_REG_REMAINING_MILAGE = 0x25, /* km ? */
NINEBOT_ESC_REG_SPEED = 0x26,
/* Not important, skipped */
NINEBOT_ESC_REG_BATTERY_VOLTAGE = 0x48,
NINEBOT_ESC_REG_BATTERY_CURRENT = 0x48,
NINEBOT_ESC_REG_LOCK_COMMAND = 0x70,
NINEBOT_ESC_REG_UNLOCK_COMMAND = 0x71,
NINEBOT_ESC_REG_ECO_MODE = 0x75,
NINEBOT_ESC_REG_REBOOT_COMMAND = 0x78,
NINEBOT_ESC_REG_POWER_DOWN_COMMAND = 0x79,
NINEBOT_ESC_REG_KERS_LEVEL = 0x7B,
NINEBOT_ESC_REG_CRUISE_CONTROL_ENABLE = 0x7C,
NINEBOT_ESC_REG_TAIL_LIGHT_ON = 0x7D,
/* Not important, skipped */
/* ... */
}
NinebotEscRegister_t;

typedef enum {
NINEBOT_BMS_REG_REMAINING_CAPACITY_mAh = 0x31,
NINEBOT_BMS_REG_REMAINING_CAPACITY = 0x32,
NINEBOT_BMS_REG_CURRENT = 0x33,
NINEBOT_BMS_REG_VOLTAGE = 0x34,
NINEBOT_BMS_REG_VOLTAGE_CELL = 0x40, /* Add 1 byte for each cell. (Ex: Cell 3 = 0x42, up to cell 10 at 0x49) */
}
NinebotBmsRegister_t;

typedef struct
{
unsigned payloadLen: 8;
unsigned sndr: 8;
unsigned recv: 8;
unsigned cmd: 8;
unsigned cmdArg: 8;
}
NinebotMessageHeader_t;

struct NinebotBleBroadcastCommand_t
{
NinebotBleBroadcastCommand_t() : len(4) {}
const unsigned len:8;
unsigned thr:8;
unsigned brk:8;
unsigned unk:8;
unsigned nbp:8;
};

struct NinebotBleBroadcastCommandAnsw_t
{
NinebotBleBroadcastCommandAnsw_t() : len(6) {}
const unsigned len:8;
unsigned thr:8;
unsigned brk:8;
unsigned unk:8;
unsigned nbp:8;
unsigned unk0:8;
unsigned unk1:8;
};

class NinebotMessage
{
private:
NinebotMessageHeader_t _msgHeader;
std::vector<uint8_t> _payload;
public:
NinebotMessage(uint8_t *buf);
NinebotMessage(NinebotMessageHeader_t *hdr, uint8_t *payload);

NinebotMessageHeader_t getHeader(void);
std::vector<uint8_t> getPayload(void);
NinebotMessageCkSum_t getCkSum(void);

std::vector<uint8_t> serialize(void);
};


76 changes: 76 additions & 0 deletions src/NinebotMessageIntercept.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#include <stdio.h>
#include <memory.h>

#include "NinebotMessageIntercept.hpp"


NinebotMessageIntercept::NinebotMessageIntercept(
NinebotMessageStream *activeStream, NinebotDeviceAddr_t device)
{
_deviceAddr = device;
_activeStream = activeStream;
}

uint8_t NinebotMessageIntercept::readNextByte(void)
{
int _data;
while(1){
_data = _activeStream->read();
if (_data >= 0) return (uint8_t) _data;
}
}

NinebotMessage NinebotMessageIntercept::awaitMessage(void)
{
uint8_t _data;
uint8_t _NinebotHeader[] = NINEBOT_PACKET_HEADER;

uint8_t headerBuf[NINEBOT_MESSAGE_HEADER_LEN];
NinebotMessageHeader_t *msgHeader = NULL;

while(1){

while(1)
{
_data = readNextByte();
loopStart:
if (_data != _NinebotHeader[0])
continue;
_data = readNextByte();
if (_data != _NinebotHeader[1])
goto loopStart;
break;
}

for (int i=0; i<NINEBOT_MESSAGE_HEADER_LEN; i++)
headerBuf[i] = readNextByte();

msgHeader = (NinebotMessageHeader_t*) headerBuf;

if ( _deviceAddr != NINEBOT_ADDR_ANY && msgHeader->recv != _deviceAddr )
/* We don't care. */
continue;

int transferLen = NINEBOT_MESSAGE_HEADER_LEN + msgHeader->payloadLen;
uint8_t message[transferLen];

memcpy(message, headerBuf, NINEBOT_MESSAGE_HEADER_LEN);
for (int i=NINEBOT_MESSAGE_HEADER_LEN; i<transferLen; i++)
message[i] = readNextByte();

uint8_t ck0 = readNextByte();
uint8_t ck1 = readNextByte();

NinebotMessage NinebotMessage(message);
NinebotMessageCkSum_t ck = NinebotMessage.getCkSum();

if (ck.ck0 == ck0 && ck.ck1 == ck1)
{
return NinebotMessage;
}
else
{
/* packet lost */;
}
}
}
24 changes: 24 additions & 0 deletions src/NinebotMessageIntercept.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <memory>

#include "NinebotMessageDefinitions.hpp"
#include "NinebotMessageUtils.hpp"

class NinebotMessageStream
{
public:
virtual void write(int) = 0;
virtual int read(void) = 0;
};

class NinebotMessageIntercept
{
private:
NinebotMessageStream *_activeStream;
NinebotDeviceAddr_t _deviceAddr;
uint8_t readNextByte();
public:
NinebotMessageIntercept(NinebotMessageStream *activeStream, NinebotDeviceAddr_t device);
NinebotMessage awaitMessage(void);
};
Loading

0 comments on commit 0bd0c5b

Please sign in to comment.