|
|
|
@ -0,0 +1,226 @@
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
|
#include <BLEDevice.h>
|
|
|
|
|
#include <BLEUtils.h>
|
|
|
|
|
#include <BLEScan.h>
|
|
|
|
|
#include <BLEAdvertisedDevice.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define I2C_SDA 21
|
|
|
|
|
#define I2C_SCL 22
|
|
|
|
|
|
|
|
|
|
#include "axp20x.h"
|
|
|
|
|
AXP20X_Class axp;
|
|
|
|
|
bool axp192_found = false;
|
|
|
|
|
|
|
|
|
|
#include <WiFi.h>
|
|
|
|
|
#include <MQTT.h>
|
|
|
|
|
|
|
|
|
|
#ifndef WIFI_SSID
|
|
|
|
|
#define WIFI_SSID "wifi_ssid"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef WIFI_PASSWORD
|
|
|
|
|
#define WIFI_PASSWORD "wifi_pw"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define MQTT_HOST "IP_or_Hostname"
|
|
|
|
|
#define MQTT_USER "username"
|
|
|
|
|
#define MQTT_PASS "password"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
#define USE_GPS
|
|
|
|
|
#ifdef USE_GPS
|
|
|
|
|
#define GPS_SERIAL_NUM 1
|
|
|
|
|
#define GPS_BAUDRATE 9600
|
|
|
|
|
#define GPS_POWER_CTRL_CH 3 // AXP192_LDO3
|
|
|
|
|
#include <TinyGPSPlus.h>
|
|
|
|
|
TinyGPSPlus _gps;
|
|
|
|
|
HardwareSerial _serial_gps(GPS_SERIAL_NUM);
|
|
|
|
|
#endif
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
WiFiClient net;
|
|
|
|
|
MQTTClient client;
|
|
|
|
|
const char* mqtt_server = MQTT_HOST;
|
|
|
|
|
|
|
|
|
|
BLEScan* pBLEScan;
|
|
|
|
|
|
|
|
|
|
const int scanTimeSeconds = 1;
|
|
|
|
|
|
|
|
|
|
// remember that structs may be extended/packed to match byte boundaries
|
|
|
|
|
struct AdvDataTemps {
|
|
|
|
|
uint8_t batt; // 1byte
|
|
|
|
|
uint16_t addr1; // 4byte
|
|
|
|
|
uint16_t temp1;
|
|
|
|
|
uint16_t addr2; // 4byte
|
|
|
|
|
uint16_t temp2;
|
|
|
|
|
uint16_t addr3; // 4byte
|
|
|
|
|
uint16_t temp3;
|
|
|
|
|
uint16_t addr4; // 4byte
|
|
|
|
|
uint16_t temp4;
|
|
|
|
|
uint16_t addr5; // 4byte
|
|
|
|
|
uint16_t temp5;
|
|
|
|
|
} advdat;
|
|
|
|
|
|
|
|
|
|
std::string string_to_hex(const std::string& input)
|
|
|
|
|
{
|
|
|
|
|
static const char hex_digits[] = "0123456789abcdef";
|
|
|
|
|
|
|
|
|
|
std::string output;
|
|
|
|
|
output.reserve(input.length() * 2);
|
|
|
|
|
for (unsigned char c : input)
|
|
|
|
|
{
|
|
|
|
|
output.push_back(hex_digits[c >> 4]);
|
|
|
|
|
output.push_back(hex_digits[c & 15]);
|
|
|
|
|
}
|
|
|
|
|
return output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define MSG_BUFFER_SIZE (50)
|
|
|
|
|
char msg[MSG_BUFFER_SIZE];
|
|
|
|
|
char msgGW[MSG_BUFFER_SIZE];
|
|
|
|
|
|
|
|
|
|
class AdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
|
|
|
|
void onResult(BLEAdvertisedDevice advertisedDevice) {
|
|
|
|
|
if (strcmp(advertisedDevice.getName().c_str(), "cat") == 0) {
|
|
|
|
|
Serial.print(advertisedDevice.getName().c_str());
|
|
|
|
|
|
|
|
|
|
const std::string& manufData = advertisedDevice.getManufacturerData();
|
|
|
|
|
std::string hexAdvData = string_to_hex(manufData);
|
|
|
|
|
for (int i = 0; i < hexAdvData.length(); i++) {
|
|
|
|
|
msg[i]= hexAdvData[i];
|
|
|
|
|
}
|
|
|
|
|
if (client.connected()) {
|
|
|
|
|
client.publish("sensofur/data", msg);
|
|
|
|
|
}
|
|
|
|
|
Serial.printf(": %s \n", hexAdvData.c_str());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void connect() {
|
|
|
|
|
Serial.print("checking wifi...");
|
|
|
|
|
while (WiFi.status() != WL_CONNECTED) {
|
|
|
|
|
Serial.print(".");
|
|
|
|
|
delay(1000);
|
|
|
|
|
}
|
|
|
|
|
Serial.println("connected!\n");
|
|
|
|
|
Serial.print("checking mqtt...");
|
|
|
|
|
while (!client.connect("sensofur-gw", MQTT_USER, MQTT_PASS)) {
|
|
|
|
|
Serial.print(".");
|
|
|
|
|
delay(1000);
|
|
|
|
|
}
|
|
|
|
|
client.subscribe("sensofur/keepalive");
|
|
|
|
|
Serial.println("connected!\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void axpInit() {
|
|
|
|
|
if (!axp.begin(Wire, AXP192_SLAVE_ADDRESS)) {
|
|
|
|
|
Serial.println("AXP192 Begin PASS");
|
|
|
|
|
} else {
|
|
|
|
|
Serial.println("AXP192 Begin FAIL");
|
|
|
|
|
}
|
|
|
|
|
axp.setChgLEDMode(AXP20X_LED_BLINK_4HZ);
|
|
|
|
|
Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.println("----------------------------------------");
|
|
|
|
|
|
|
|
|
|
axp.setPowerOutPut(AXP192_LDO2, AXP202_ON); // LORA radio
|
|
|
|
|
axp.setPowerOutPut(AXP192_LDO3, AXP202_ON); // GPS main power
|
|
|
|
|
axp.setPowerOutPut(AXP192_DCDC2, AXP202_ON);
|
|
|
|
|
axp.setPowerOutPut(AXP192_EXTEN, AXP202_ON);
|
|
|
|
|
axp.setPowerOutPut(AXP192_DCDC1, AXP202_ON);
|
|
|
|
|
axp.setDCDC1Voltage(3300); // for the OLED power
|
|
|
|
|
|
|
|
|
|
Serial.printf("DCDC1: %s\n", axp.isDCDC1Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("DCDC2: %s\n", axp.isDCDC2Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("LDO2: %s\n", axp.isLDO2Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("LDO3: %s\n", axp.isLDO3Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("DCDC3: %s\n", axp.isDCDC3Enable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
Serial.printf("Exten: %s\n", axp.isExtenEnable() ? "ENABLE" : "DISABLE");
|
|
|
|
|
|
|
|
|
|
axp.adc1Enable(AXP202_BATT_CUR_ADC1, 1);
|
|
|
|
|
axp.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ | AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ, 1);
|
|
|
|
|
axp.clearIRQ();
|
|
|
|
|
|
|
|
|
|
Serial.println();
|
|
|
|
|
Serial.flush();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setup() {
|
|
|
|
|
Serial.begin(115200);
|
|
|
|
|
Serial.println("Scanning...");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Wire.begin(I2C_SDA, I2C_SCL);
|
|
|
|
|
axpInit();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Serial.printf("Connecting to WiFi %s\n", WIFI_SSID);
|
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
|
|
|
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
|
|
|
|
|
while (WiFi.status() != WL_CONNECTED) { delay(1000); }
|
|
|
|
|
Serial.println("WiFi connected.");
|
|
|
|
|
|
|
|
|
|
client.begin(mqtt_server, 1883, net);
|
|
|
|
|
connect();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BLEDevice::init("");
|
|
|
|
|
pBLEScan = BLEDevice::getScan(); // create new scan
|
|
|
|
|
pBLEScan->setAdvertisedDeviceCallbacks(new AdvertisedDeviceCallbacks());
|
|
|
|
|
pBLEScan->setActiveScan(false); // active scan (true) uses more power, but get results faster
|
|
|
|
|
pBLEScan->setInterval(100);
|
|
|
|
|
pBLEScan->setWindow(99); // less or equal setInterval value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct GWData {
|
|
|
|
|
uint16_t volt;
|
|
|
|
|
int16_t current;
|
|
|
|
|
} gwData;
|
|
|
|
|
|
|
|
|
|
long last = 0;
|
|
|
|
|
void loop() {
|
|
|
|
|
if (millis() - last > 15e3) {
|
|
|
|
|
last = millis();
|
|
|
|
|
|
|
|
|
|
axp.readIRQ();
|
|
|
|
|
if (axp.isChargingIRQ()) {
|
|
|
|
|
Serial.println("Charging");
|
|
|
|
|
} else {
|
|
|
|
|
Serial.println("No Charging");
|
|
|
|
|
}
|
|
|
|
|
if (axp.isVbusRemoveIRQ()) {
|
|
|
|
|
Serial.println("No Charging");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gwData.volt = (uint16_t)axp.getBattVoltage();
|
|
|
|
|
gwData.current = (int16_t)(axp.getBattChargeCurrent() - axp.getBattDischargeCurrent());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < sizeof(gwData); i++) msgGW[i] = ((char*)&gwData)[i];
|
|
|
|
|
if (client.connected()) {
|
|
|
|
|
Serial.println("publishing gw stats");
|
|
|
|
|
client.publish("sensofur/gateway", msgGW);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//Serial.printf("getVbusVoltage: %d\n", axp.getVbusVoltage());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
client.loop();
|
|
|
|
|
if (!client.connected()) {
|
|
|
|
|
connect();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BLEScanResults foundDevices = pBLEScan->start(scanTimeSeconds, false);
|
|
|
|
|
pBLEScan->clearResults();
|
|
|
|
|
}
|