Skip to content

Instantly share code, notes, and snippets.

@vinthewrench
Created February 9, 2022 22:58
Show Gist options
  • Save vinthewrench/4d2046c3d3cc0bae7e2fa54bdfb89dac to your computer and use it in GitHub Desktop.
Save vinthewrench/4d2046c3d3cc0bae7e2fa54bdfb89dac to your computer and use it in GitHub Desktop.
Using gattlib to read values from victron smart shunt bluetooth
/*
clang++ -Wall -o testshunt testshunt.c /usr/lib/libgattlib.so
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "gattlib.h"
volatile bool g_operation_completed;
/*
As Documented at
https://community.victronenergy.com/questions/93919/victron-bluetooth-ble-protocol-publication.html
*/
const char* uuid_str_SOC = "65970fff-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_V = "6597ed8d-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_A = "6597ed8c-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_P = "6597ed8e-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_Consumed = "6597eeff-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_tempK = "6597edec-4bda-4c1e-af4b-551c4cf74769";
const char* uuid_str_t2go = "65970ffe-4bda-4c1e-af4b-551c4cf74769";
#define MINS_PER_HOUR ((int16_t)(60 ))
#define MINS_PER_DAY ((int16_t)(MINS_PER_HOUR * 24 ))
static void breakDuration(int16_t minutesIn,
int16_t *days, int16_t *hours, int16_t *mins ){
uint16_t remainingMinutes = minutesIn;
*days = (remainingMinutes/ MINS_PER_DAY);
remainingMinutes = minutesIn - (*days * MINS_PER_DAY);
*hours = (remainingMinutes / MINS_PER_HOUR) ;
remainingMinutes = minutesIn - ( (*days * MINS_PER_DAY) + (*hours * MINS_PER_HOUR));
*mins = remainingMinutes;
}
static void connect_cb(gatt_connection_t* connection, void* user_data) {
if (connection != NULL) {
uuid_t uuid;
int err = GATTLIB_SUCCESS;
printf("Connected \n");
// get SOC
if ( gattlib_string_to_uuid(uuid_str_SOC, strlen(uuid_str_SOC) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i) / 100.0;
printf("\t%-10s: %0.2f%%\n", "SOC", val);
free(buffer);
}
}
// Get Battery Voltage
if ( gattlib_string_to_uuid(uuid_str_V, strlen(uuid_str_V) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i) / 100.0;
printf("\t%-10s: %0.2fV\n", "Voltage", val);
free(buffer);
}
}
// Get Battery Current
if ( gattlib_string_to_uuid(uuid_str_A, strlen(uuid_str_A) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
uint16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i) / 1000.0;
printf("\t%-10s: %0.2fA\n", "Current", val);
free(buffer);
}
}
// Get Battery Power
if ( gattlib_string_to_uuid(uuid_str_P, strlen(uuid_str_P) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i);
printf("\t%-10s: %0.2fW\n", "Power", val);
free(buffer);
}
}
// Consumed Ah
if ( gattlib_string_to_uuid(uuid_str_Consumed, strlen(uuid_str_Consumed) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i) / 10.0;
printf("\t%-10s: %0.2fAh\n", "Consumed", val);
free(buffer);
}
}
// Time remaining
if ( gattlib_string_to_uuid(uuid_str_t2go, strlen(uuid_str_t2go) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
if(i == -1)
printf("\t%-10s: %s\n", "Time 2 Go", "Infinite");
else
{
int16_t days, hours, mins;
breakDuration(i, &days, &hours, &mins);
//printf("%02x %02x " , buffer[0],buffer[1]);
printf("\t%-10s: ","Time 2 Go");
if(days > 0) printf("%d Days ",days);
if(hours > 0) printf("%d Hours ", hours);
printf("%d Mins ", mins);
printf("\n");
}
free(buffer);
}
}
// Temperaure in Kelvin Ah
if ( gattlib_string_to_uuid(uuid_str_tempK, strlen(uuid_str_tempK) + 1, &uuid) == 0){
size_t len;
uint8_t *buffer = NULL;
err = gattlib_read_char_by_uuid(connection, &uuid, (void **)&buffer, &len);
if(err == GATTLIB_SUCCESS){
int16_t i = (buffer[1] << 8) | buffer[0];
double val = (double) (i) / 100.0;
val = (val - 273.15)* 1.8000 + 32.00;
printf("\t%-10s: %0.2f°F\n", "Bat Temp", val);
free(buffer);
}
}
}
g_operation_completed = true;
}
int main(int argc, char *arg[]) {
gatt_connection_t* con;
const char* deviceID = "CA:9C:B9:8D:E3:70";
g_operation_completed = false;
con = gattlib_connect_async(NULL, deviceID, BDADDR_LE_RANDOM, connect_cb, 0);
if (con == NULL) {
fprintf(stderr, "Fail to connect to the bluetooth device %s.\n",deviceID);
return 1;
} else {
while (!g_operation_completed);
gattlib_disconnect(con);
printf("Disconnected \n");
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment