Merge pull request #36 from roarfred/CreatingAmsToMqttBridge

Creating ams to mqtt bridge
This commit is contained in:
Roar Fredriksen 2018-03-20 21:09:34 +01:00 committed by GitHub
commit 99ecba63e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1173 additions and 0 deletions

View File

@ -0,0 +1,501 @@
/*
Name: AmsToMqttBridge.ino
Created: 3/13/2018 7:40:28 PM
Author: roarf
*/
#include <DallasTemperature.h>
#include <OneWire.h>
#include <ArduinoJson.h>
#include <PubSubClient.h>
#include <HanReader.h>
#include <Kaifa.h>
#include <Kamstrup.h>
#include "configuration.h"
#include "accesspoint.h"
#define WIFI_CONNECTION_TIMEOUT 30000;
#define TEMP_SENSOR_PIN 5 // Temperature sensor connected to GPIO5
#define LED_PIN 2 // The blue on-board LED of the ESP
OneWire oneWire(TEMP_SENSOR_PIN);
DallasTemperature tempSensor(&oneWire);
long lastTempDebug = 0;
// Object used to boot as Access Point
accesspoint ap;
// WiFi client and MQTT client
WiFiClient *client;
PubSubClient mqtt;
// Object used for debugging
HardwareSerial* debugger = NULL;
// The HAN Port reader, used to read serial data and decode DLMS
HanReader hanReader;
// the setup function runs once when you press reset or power the board
void setup()
{
// Uncomment to debug over the same port as used for HAN communication
debugger = &Serial;
if (debugger) {
// Setup serial port for debugging
debugger->begin(2400, SERIAL_8E1);
while (!&debugger);
debugger->println("Started...");
}
// Assign pin for boot as AP
delay(1000);
pinMode(0, INPUT_PULLUP);
// Flash the blue LED, to indicate we can boot as AP now
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Initialize the AP
ap.setup(0, Serial);
// Turn off the blue LED
digitalWrite(LED_PIN, HIGH);
if (!ap.isActivated)
{
setupWiFi();
hanReader.setup(&Serial, 2400, SERIAL_8E1, debugger);
// Compensate for the known Kaifa bug
hanReader.compensateFor09HeaderBug = (ap.config.meterType == 1);
}
}
// the loop function runs over and over again until power down or reset
void loop()
{
// Only do normal stuff if we're not booted as AP
if (!ap.loop())
{
// turn off the blue LED
digitalWrite(LED_PIN, HIGH);
// allow the MQTT client some resources
mqtt.loop();
delay(10); // <- fixes some issues with WiFi stability
// Reconnect to WiFi and MQTT as needed
if (!mqtt.connected()) {
MQTT_connect();
}
else
{
// Read data from the HAN port
readHanPort();
}
}
else
{
// Continously flash the blue LED when AP mode
if (millis() / 1000 % 2 == 0)
digitalWrite(LED_PIN, LOW);
else
digitalWrite(LED_PIN, HIGH);
}
}
void setupWiFi()
{
// Turn off AP
WiFi.enableAP(false);
// Connect to WiFi
WiFi.begin(ap.config.ssid, ap.config.ssidPassword);
// Initialize WiFi and MQTT clients
if (ap.config.isSecure())
client = new WiFiClientSecure();
else
client = new WiFiClient();
mqtt = PubSubClient(*client);
mqtt.setServer(ap.config.mqtt, ap.config.mqttPort);
// Direct incoming MQTT messages
if (ap.config.mqttSubscribeTopic != 0 && strlen(ap.config.mqttSubscribeTopic) > 0)
mqtt.setCallback(mqttMessageReceived);
// Connect to the MQTT server
MQTT_connect();
// Notify everyone we're here!
sendMqttData("Connected!");
}
void mqttMessageReceived(char* topic, unsigned char* payload, unsigned int length)
{
// make the incoming message a null-terminated string
char message[1000];
for (int i = 0; i < length; i++)
message[i] = payload[i];
message[length] = 0;
if (debugger) {
debugger->println("Incoming MQTT message:");
debugger->print("[");
debugger->print(topic);
debugger->print("] ");
debugger->println(message);
}
// Do whatever needed here...
// Ideas could be to query for values or to initiate OTA firmware update
}
void readHanPort()
{
if (hanReader.read())
{
// Flash LED on, this shows us that data is received
digitalWrite(LED_PIN, LOW);
// Get the list identifier
int listSize = hanReader.getListSize();
switch (ap.config.meterType)
{
case 1: // Kaifa
readHanPort_Kaifa(listSize);
break;
case 2: // Kamstrup
readHanPort_Kamstrup(listSize);
break;
case 3: // Aidon
readHanPort_Aidon(listSize);
break;
default:
debugger->print("Meter type ");
debugger->print(ap.config.meterType, HEX);
debugger->println(" is unknown");
delay(10000);
break;
}
// Flash LED off
digitalWrite(LED_PIN, HIGH);
}
}
void readHanPort_Aidon(int listSize)
{
if (debugger)
debugger->println("Meter type Aidon is not yet implemented");
delay(10000);
}
void readHanPort_Kamstrup(int listSize)
{
// Only care for the ACtive Power Imported, which is found in the first list
if (listSize == (int)Kamstrup::List1 || listSize == (int)Kamstrup::List2)
{
if (listSize == (int)Kamstrup::List1)
{
String id = hanReader.getString((int)Kamstrup_List1::ListVersionIdentifier);
if (debugger) debugger->println(id);
}
else if (listSize == (int)Kamstrup::List2)
{
String id = hanReader.getString((int)Kamstrup_List2::ListVersionIdentifier);
if (debugger) debugger->println(id);
}
// Get the timestamp (as unix time) from the package
time_t time = hanReader.getPackageTime();
if (debugger) debugger->print("Time of the package is: ");
if (debugger) debugger->println(time);
// Define a json object to keep the data
StaticJsonBuffer<500> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
// Any generic useful info here
root["id"] = WiFi.macAddress();
root["up"] = millis();
root["t"] = time;
// Add a sub-structure to the json object,
// to keep the data from the meter itself
JsonObject& data = root.createNestedObject("data");
// Get the temperature too
tempSensor.requestTemperatures();
float temperature = tempSensor.getTempCByIndex(0);
data["temp"] = temperature;
// Based on the list number, get all details
// according to OBIS specifications for the meter
if (listSize == (int)Kamstrup::List1)
{
data["lv"] = hanReader.getString((int)Kamstrup_List1::ListVersionIdentifier);
data["id"] = hanReader.getString((int)Kamstrup_List1::MeterID);
data["type"] = hanReader.getString((int)Kamstrup_List1::MeterType);
data["P"] = hanReader.getInt((int)Kamstrup_List1::ActiveImportPower);
data["Q"] = hanReader.getInt((int)Kamstrup_List1::ReactiveImportPower);
data["I1"] = hanReader.getInt((int)Kamstrup_List1::CurrentL1);
data["I2"] = hanReader.getInt((int)Kamstrup_List1::CurrentL2);
data["I3"] = hanReader.getInt((int)Kamstrup_List1::CurrentL3);
data["U1"] = hanReader.getInt((int)Kamstrup_List1::VoltageL1);
data["U2"] = hanReader.getInt((int)Kamstrup_List1::VoltageL2);
data["U3"] = hanReader.getInt((int)Kamstrup_List1::VoltageL3);
}
else if (listSize == (int)Kamstrup::List2)
{
data["lv"] = hanReader.getString((int)Kamstrup_List2::ListVersionIdentifier);;
data["id"] = hanReader.getString((int)Kamstrup_List2::MeterID);
data["type"] = hanReader.getString((int)Kamstrup_List2::MeterType);
data["P"] = hanReader.getInt((int)Kamstrup_List2::ActiveImportPower);
data["Q"] = hanReader.getInt((int)Kamstrup_List2::ReactiveImportPower);
data["I1"] = hanReader.getInt((int)Kamstrup_List2::CurrentL1);
data["I2"] = hanReader.getInt((int)Kamstrup_List2::CurrentL2);
data["I3"] = hanReader.getInt((int)Kamstrup_List2::CurrentL3);
data["U1"] = hanReader.getInt((int)Kamstrup_List2::VoltageL1);
data["U2"] = hanReader.getInt((int)Kamstrup_List2::VoltageL2);
data["U3"] = hanReader.getInt((int)Kamstrup_List2::VoltageL3);
data["tPI"] = hanReader.getInt((int)Kamstrup_List2::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt((int)Kamstrup_List2::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt((int)Kamstrup_List2::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt((int)Kamstrup_List2::CumulativeReactiveExportEnergy);
}
// Write the json to the debug port
if (debugger) {
debugger->print("Sending data to MQTT: ");
root.printTo(*debugger);
debugger->println();
}
// Make sure we have configured a publish topic
if (ap.config.mqttPublishTopic == 0 || strlen(ap.config.mqttPublishTopic) == 0)
return;
// Publish the json to the MQTT server
char msg[1024];
root.printTo(msg, 1024);
mqtt.publish(ap.config.mqttPublishTopic, msg);
}
}
void readHanPort_Kaifa(int listSize)
{
// Only care for the ACtive Power Imported, which is found in the first list
if (listSize == (int)Kaifa::List1 || listSize == (int)Kaifa::List2 || listSize == (int)Kaifa::List3)
{
if (listSize == (int)Kaifa::List1)
{
if (debugger) debugger->println(" (list #1 has no ID)");
}
else
{
String id = hanReader.getString((int)Kaifa_List2::ListVersionIdentifier);
if (debugger) debugger->println(id);
}
// Get the timestamp (as unix time) from the package
time_t time = hanReader.getPackageTime();
if (debugger) debugger->print("Time of the package is: ");
if (debugger) debugger->println(time);
// Define a json object to keep the data
//StaticJsonBuffer<500> jsonBuffer;
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
// Any generic useful info here
root["id"] = WiFi.macAddress();
root["up"] = millis();
root["t"] = time;
// Add a sub-structure to the json object,
// to keep the data from the meter itself
JsonObject& data = root.createNestedObject("data");
// Get the temperature too
tempSensor.requestTemperatures();
float temperature = tempSensor.getTempCByIndex(0);
data["temp"] = String(temperature);
// Based on the list number, get all details
// according to OBIS specifications for the meter
if (listSize == (int)Kaifa::List1)
{
data["P"] = hanReader.getInt((int)Kaifa_List1::ActivePowerImported);
}
else if (listSize == (int)Kaifa::List2)
{
data["lv"] = hanReader.getString((int)Kaifa_List2::ListVersionIdentifier);
data["id"] = hanReader.getString((int)Kaifa_List2::MeterID);
data["type"] = hanReader.getString((int)Kaifa_List2::MeterType);
data["P"] = hanReader.getInt((int)Kaifa_List2::ActiveImportPower);
data["Q"] = hanReader.getInt((int)Kaifa_List2::ReactiveImportPower);
data["I1"] = hanReader.getInt((int)Kaifa_List2::CurrentL1);
data["I2"] = hanReader.getInt((int)Kaifa_List2::CurrentL2);
data["I3"] = hanReader.getInt((int)Kaifa_List2::CurrentL3);
data["U1"] = hanReader.getInt((int)Kaifa_List2::VoltageL1);
data["U2"] = hanReader.getInt((int)Kaifa_List2::VoltageL2);
data["U3"] = hanReader.getInt((int)Kaifa_List2::VoltageL3);
}
else if (listSize == (int)Kaifa::List3)
{
data["lv"] = hanReader.getString((int)Kaifa_List3::ListVersionIdentifier);;
data["id"] = hanReader.getString((int)Kaifa_List3::MeterID);
data["type"] = hanReader.getString((int)Kaifa_List3::MeterType);
data["P"] = hanReader.getInt((int)Kaifa_List3::ActiveImportPower);
data["Q"] = hanReader.getInt((int)Kaifa_List3::ReactiveImportPower);
data["I1"] = hanReader.getInt((int)Kaifa_List3::CurrentL1);
data["I2"] = hanReader.getInt((int)Kaifa_List3::CurrentL2);
data["I3"] = hanReader.getInt((int)Kaifa_List3::CurrentL3);
data["U1"] = hanReader.getInt((int)Kaifa_List3::VoltageL1);
data["U2"] = hanReader.getInt((int)Kaifa_List3::VoltageL2);
data["U3"] = hanReader.getInt((int)Kaifa_List3::VoltageL3);
data["tPI"] = hanReader.getInt((int)Kaifa_List3::CumulativeActiveImportEnergy);
data["tPO"] = hanReader.getInt((int)Kaifa_List3::CumulativeActiveExportEnergy);
data["tQI"] = hanReader.getInt((int)Kaifa_List3::CumulativeReactiveImportEnergy);
data["tQO"] = hanReader.getInt((int)Kaifa_List3::CumulativeReactiveExportEnergy);
}
// Write the json to the debug port
if (debugger) {
debugger->print("Sending data to MQTT: ");
root.printTo(*debugger);
debugger->println();
}
// Make sure we have configured a publish topic
if (ap.config.mqttPublishTopic == 0 || strlen(ap.config.mqttPublishTopic) == 0)
return;
// Publish the json to the MQTT server
char msg[1024];
root.printTo(msg, 1024);
mqtt.publish(ap.config.mqttPublishTopic, msg);
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect()
{
// Connect to WiFi access point.
if (debugger)
{
debugger->println();
debugger->println();
debugger->print("Connecting to WiFi network ");
debugger->println(ap.config.ssid);
}
if (WiFi.status() != WL_CONNECTED)
{
// Make one first attempt at connect, this seems to considerably speed up the first connection
WiFi.disconnect();
WiFi.begin(ap.config.ssid, ap.config.ssidPassword);
delay(1000);
}
// Wait for the WiFi connection to complete
long vTimeout = millis() + WIFI_CONNECTION_TIMEOUT;
while (WiFi.status() != WL_CONNECTED) {
delay(50);
if (debugger) debugger->print(".");
// If we timed out, disconnect and try again
if (vTimeout < millis())
{
if (debugger)
{
debugger->print("Timout during connect. WiFi status is: ");
debugger->println(WiFi.status());
}
WiFi.disconnect();
WiFi.begin(ap.config.ssid, ap.config.ssidPassword);
vTimeout = millis() + WIFI_CONNECTION_TIMEOUT;
}
yield();
}
if (debugger) {
debugger->println();
debugger->println("WiFi connected");
debugger->println("IP address: ");
debugger->println(WiFi.localIP());
debugger->print("\nconnecting to MQTT: ");
debugger->print(ap.config.mqtt);
debugger->print(", port: ");
debugger->print(ap.config.mqttPort);
debugger->println();
}
// Wait for the MQTT connection to complete
while (!mqtt.connected()) {
// Connect to a unsecure or secure MQTT server
if ((ap.config.mqttUser == 0 && mqtt.connect(ap.config.mqttClientID)) ||
(ap.config.mqttUser != 0 && mqtt.connect(ap.config.mqttClientID, ap.config.mqttUser, ap.config.mqttPass)))
{
if (debugger) debugger->println("\nSuccessfully connected to MQTT!");
// Subscribe to the chosen MQTT topic, if set in configuration
if (ap.config.mqttSubscribeTopic != 0 && strlen(ap.config.mqttSubscribeTopic) > 0)
{
mqtt.subscribe(ap.config.mqttSubscribeTopic);
if (debugger) debugger->printf(" Subscribing to [%s]\r\n", ap.config.mqttSubscribeTopic);
}
}
else
{
if (debugger)
{
debugger->print(".");
debugger->print("failed, mqtt.state() = ");
debugger->print(mqtt.state());
debugger->println(" trying again in 5 seconds");
}
// Wait 2 seconds before retrying
mqtt.disconnect();
delay(2000);
}
// Allow some resources for the WiFi connection
yield();
}
}
// Send a simple string embedded in json over MQTT
void sendMqttData(String data)
{
// Make sure we have configured a publish topic
if (ap.config.mqttPublishTopic == 0 || strlen(ap.config.mqttPublishTopic) == 0)
return;
// Make sure we're connected
if (!client->connected() || !mqtt.connected()) {
MQTT_connect();
}
// Build a json with the message in a "data" attribute
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
json["id"] = WiFi.macAddress();
json["up"] = millis();
json["data"] = data;
// Stringify the json
String msg;
json.printTo(msg);
// Send the json over MQTT
mqtt.publish(ap.config.mqttPublishTopic, msg.c_str());
}

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.16
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AmsToMqttBridge", "AmsToMqttBridge.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HanReader", "..\HanReader\HanReader.vcxitems", "{CD0F5364-923B-49E4-8BE5-EA7D8A60DF80}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\HanReader\HanReader.vcxitems*{c5f80730-f44f-4478-bdae-6634efc2ca88}*SharedItemsImports = 4
..\HanReader\HanReader.vcxitems*{cd0f5364-923b-49e4-8be5-ea7d8a60df80}*SharedItemsImports = 9
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
{C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5DFC14B6-4C33-4307-8BDA-C050F68A74F6}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5F80730-F44F-4478-BDAE-6634EFC2CA88}</ProjectGuid>
<RootNamespace>AmsToMqttBridge</RootNamespace>
<ProjectName>AmsToMqttBridge</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>
</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>
</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="..\HanReader\HanReader.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>$(ProjectDir)..\AmsToMqttBridge;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src;$(ProjectDir)..\HanReader\src;$(ProjectDir)..\..\..\..\..\..\..\..\..\Program Files (x86)\Arduino\libraries;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries;$(ProjectDir)..\..\..\..\..\..\..\Google Drive\Private\Elektronikk\Arduino\libraries;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\libb64;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\spiffs;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\generic;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\lwip\include;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\xtensa-lx106-elf;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\lib\gcc\xtensa-lx106-elf\4.8.2\include;$(ProjectDir)..\..\..\..\..\..\..\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<ForcedIncludeFiles>$(ProjectDir)__vm\.AmsToMqttBridge.vsarduino.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<PreprocessorDefinitions>__ESP8266_ESp8266__;__ESP8266_ESP8266__;__ets__;ICACHE_FLASH;F_CPU=80000000L;LWIP_OPEN_SRC;ARDUINO=106012;ARDUINO_ESP8266_ESP01;ARDUINO_ARCH_ESP8266;ESP8266;__cplusplus=201103L;_VMICRO_INTELLISENSE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectCapability Include="VisualMicro" />
</ItemGroup>
<PropertyGroup>
<DebuggerFlavor>VisualMicroDebugger</DebuggerFlavor>
</PropertyGroup>
<ItemGroup>
<None Include="AmsToMqttBridge.ino">
<FileType>CppCode</FileType>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="accesspoint.h" />
<ClInclude Include="configuration.h" />
<ClInclude Include="__vm\.AmsToMqttBridge.vsarduino.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="accesspoint.cpp" />
<ClCompile Include="configuration.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<ProjectExtensions>
<VisualStudio>
<UserProperties custom_esp8266_generic_UploadSpeed="256000" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="AmsToMqttBridge.ino" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="__vm\.AmsToMqttBridge.vsarduino.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,46 @@
// ap.h
#ifndef _ACCESSPOINT_h
#define _ACCESSPOINT_h
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DNSServer.h>
#include "configuration.h"
class accesspoint {
public:
void setup(int accessPointButtonPin, Stream& debugger);
bool loop();
bool hasConfig();
configuration config;
bool isActivated = false;
private:
const char* AP_SSID = "AMS2MQTT";
// DNS server
const byte DNS_PORT = 53;
DNSServer dnsServer;
static size_t print(const char* text);
static size_t println(const char* text);
static size_t print(const Printable& data);
static size_t println(const Printable& data);
// Web server
static void handleRoot();
static void handleSave();
static ESP8266WebServer server;
static Stream* debugger;
};
#endif

View File

@ -0,0 +1,230 @@
//
//
//
#include "configuration.h"
bool configuration::hasConfig()
{
bool hasConfig = false;
EEPROM.begin(EEPROM_SIZE);
hasConfig = EEPROM.read(EEPROM_CONFIG_ADDRESS) == EEPROM_CHECK_SUM;
EEPROM.end();
return hasConfig;
}
bool configuration::save()
{
int address = EEPROM_CONFIG_ADDRESS;
EEPROM.begin(EEPROM_SIZE);
EEPROM.put(address, EEPROM_CHECK_SUM);
address++;
address += saveString(address, ssid);
address += saveString(address, ssidPassword);
address += saveByte(address, meterType);
address += saveString(address, mqtt);
address += saveInt(address, mqttPort);
address += saveString(address, mqttClientID);
address += saveString(address, mqttPublishTopic);
address += saveString(address, mqttSubscribeTopic);
if (isSecure()) {
address += saveBool(address, true);
address += saveString(address, mqttUser);
address += saveString(address, mqttPass);
}
else
address += saveBool(address, false);
bool success = EEPROM.commit();
EEPROM.end();
return success;
}
bool configuration::load()
{
int address = EEPROM_CONFIG_ADDRESS;
bool success = false;
EEPROM.begin(EEPROM_SIZE);
if (EEPROM.read(address) == EEPROM_CHECK_SUM)
{
address++;
address += readString(address, &ssid);
address += readString(address, &ssidPassword);
address += readByte(address, &meterType);
address += readString(address, &mqtt);
address += readInt(address, &mqttPort);
address += readString(address, &mqttClientID);
address += readString(address, &mqttPublishTopic);
address += readString(address, &mqttSubscribeTopic);
bool secure = false;
address += readBool(address, &secure);
if (secure)
{
address += readString(address, &mqttUser);
address += readString(address, &mqttPass);
}
else
{
mqttUser = 0;
mqttPass = 0;
}
success = true;
}
else
{
ssid = (char*)String("").c_str();
ssidPassword = (char*)String("").c_str();
meterType = (byte)0;
mqtt = (char*)String("").c_str();
mqttClientID = (char*)String("").c_str();
mqttPublishTopic = (char*)String("").c_str();
mqttSubscribeTopic = (char*)String("").c_str();
mqttUser = 0;
mqttPass = 0;
mqttPort = 1883;
}
EEPROM.end();
return success;
}
bool configuration::isSecure()
{
return (mqttUser != 0) && (String(mqttUser).length() > 0);
}
int configuration::readInt(int address, int *value)
{
int lower = EEPROM.read(address);
int higher = EEPROM.read(address + 1);
*value = lower + (higher << 8);
return 2;
}
int configuration::saveInt(int address, int value)
{
byte lowByte = value & 0xFF;
byte highByte = ((value >> 8) & 0xFF);
EEPROM.write(address, lowByte);
EEPROM.write(address + 1, highByte);
return 2;
}
int configuration::readBool(int address, bool *value)
{
byte y = EEPROM.read(address);
*value = (bool)y;
return 1;
}
int configuration::saveBool(int address, bool value)
{
byte y = (byte)value;
EEPROM.write(address, y);
return 1;
}
int configuration::readByte(int address, byte *value)
{
*value = EEPROM.read(address);
return 1;
}
int configuration::saveByte(int address, byte value)
{
EEPROM.write(address, value);
return 1;
}
void configuration::print(Stream& serial)
{
/*
char* ssid;
char* ssidPassword;
byte meterType;
char* mqtt;
int mqttPort;
char* mqttClientID;
char* mqttPublishTopic;
char* mqttSubscribeTopic;
bool secure;
char* mqttUser;
char* mqttPass;
*/
serial.println("Configuration:");
serial.println("-----------------------------------------------");
serial.printf("ssid: %s\r\n", this->ssid);
serial.printf("ssidPassword: %s\r\n", this->ssidPassword);
serial.printf("meterType: %i\r\n", this->meterType);
serial.printf("mqtt: %s\r\n", this->mqtt);
serial.printf("mqttPort: %i\r\n", this->mqttPort);
serial.printf("mqttClientID: %s\r\n", this->mqttClientID);
serial.printf("mqttPublishTopic: %s\r\n", this->mqttPublishTopic);
serial.printf("mqttSubscribeTopic: %s\r\n", this->mqttSubscribeTopic);
if (this->isSecure())
{
serial.printf("SECURE MQTT CONNECTION:\r\n");
serial.printf("mqttUser: %s\r\n", this->mqttUser);
serial.printf("mqttPass: %s\r\n", this->mqttPass);
}
serial.println("-----------------------------------------------");
}
template <class T> int configuration::writeAnything(int ee, const T& value)
{
const byte* p = (const byte*)(const void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
EEPROM.write(ee++, *p++);
return i;
}
template <class T> int configuration::readAnything(int ee, T& value)
{
byte* p = (byte*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
*p++ = EEPROM.read(ee++);
return i;
}
int configuration::readString(int pAddress, char* pString[])
{
int address = 0;
byte length = EEPROM.read(pAddress + address);
address++;
char* buffer = new char[length];
for (int i = 0; i<length; i++)
{
buffer[i] = EEPROM.read(pAddress + address++);
}
*pString = buffer;
return address;
}
int configuration::saveString(int pAddress, char* pString)
{
int address = 0;
int length = strlen(pString) + 1;
EEPROM.put(pAddress + address, length);
address++;
for (int i = 0; i < length; i++)
{
EEPROM.put(pAddress + address, pString[i]);
address++;
}
return address;
}

View File

@ -0,0 +1,56 @@
// config.h
#ifndef _CONFIGURATION_h
#define _CONFIGURATION_h
#include <EEPROM.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
class configuration {
public:
char* ssid;
char* ssidPassword;
char* mqtt;
int mqttPort;
char* mqttClientID;
char* mqttPublishTopic;
char* mqttSubscribeTopic;
char* mqttUser;
char* mqttPass;
byte meterType;
bool hasConfig();
bool isSecure();
bool save();
bool load();
void print(Stream& serial);
protected:
private:
const int EEPROM_SIZE = 512;
const byte EEPROM_CHECK_SUM = 71; // Used to check if config is stored. Change if structure changes
const int EEPROM_CONFIG_ADDRESS = 0;
int saveString(int pAddress, char* pString);
int readString(int pAddress, char* pString[]);
int saveInt(int pAddress, int pValue);
int readInt(int pAddress, int *pValue);
int saveBool(int pAddress, bool pValue);
int readBool(int pAddress, bool *pValue);
int saveByte(int pAddress, byte pValue);
int readByte(int pAddress, byte *pValue);
template <class T> int writeAnything(int ee, const T& value);
template <class T> int readAnything(int ee, T& value);
};
#endif

View File

@ -81,6 +81,8 @@ void HanReader::debugPrint(byte *buffer, int start, int length)
debug->println("");
else if ((i - start + 1) % 4 == 0)
debug->print(" ");
yield(); // Let other get some resources too
}
debug->println("");
}