Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
helgeerbe committed Sep 4, 2023
2 parents d5308b1 + 3df47d1 commit 8dd96c4
Show file tree
Hide file tree
Showing 51 changed files with 2,405 additions and 912 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ on:
paths-ignore:
- docs/**
- '**/*.md'
branches:
- master
- development
tags-ignore:
- v*
pull_request:
paths-ignore:
- docs/**
Expand Down
60 changes: 24 additions & 36 deletions include/Battery.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,44 +2,32 @@
#pragma once

#include <stdint.h>
#include <memory>
#include <mutex>

#include "BatteryStats.h"

class BatteryProvider {
public:
// returns true if the provider is ready for use, false otherwise
virtual bool init(bool verboseLogging) = 0;

virtual void deinit() = 0;
virtual void loop() = 0;
virtual std::shared_ptr<BatteryStats> getStats() const = 0;
};

class BatteryClass {
public:
uint32_t lastUpdate;

float chargeVoltage;
float chargeCurrentLimitation;
float dischargeCurrentLimitation;
uint16_t stateOfCharge;
uint32_t stateOfChargeLastUpdate;
uint16_t stateOfHealth;
float voltage;
float current;
float temperature;
bool alarmOverCurrentDischarge;
bool alarmUnderTemperature;
bool alarmOverTemperature;
bool alarmUnderVoltage;
bool alarmOverVoltage;

bool alarmBmsInternal;
bool alarmOverCurrentCharge;


bool warningHighCurrentDischarge;
bool warningLowTemperature;
bool warningHighTemperature;
bool warningLowVoltage;
bool warningHighVoltage;

bool warningBmsInternal;
bool warningHighCurrentCharge;
char manufacturer[9];
bool chargeEnabled;
bool dischargeEnabled;
bool chargeImmediately;

private:
public:
void init();
void loop();

std::shared_ptr<BatteryStats const> getStats() const;

private:
uint32_t _lastMqttPublish = 0;
mutable std::mutex _mutex;
std::unique_ptr<BatteryProvider> _upProvider = nullptr;
};

extern BatteryClass Battery;
98 changes: 98 additions & 0 deletions include/BatteryStats.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include <stdint.h>

#include "AsyncJson.h"
#include "Arduino.h"
#include "JkBmsDataPoints.h"

// mandatory interface for all kinds of batteries
class BatteryStats {
public:
String const& getManufacturer() const { return _manufacturer; }

// the last time *any* datum was updated
uint32_t getAgeSeconds() const { return (millis() - _lastUpdate) / 1000; }
bool updateAvailable(uint32_t since) const { return _lastUpdate > since; }

uint8_t getSoC() const { return _SoC; }
uint32_t getSoCAgeSeconds() const { return (millis() - _lastUpdateSoC) / 1000; }

// convert stats to JSON for web application live view
virtual void getLiveViewData(JsonVariant& root) const;

virtual void mqttPublish() const;

bool isValid() const { return _lastUpdateSoC > 0 && _lastUpdate > 0; }

protected:
template<typename T>
void addLiveViewValue(JsonVariant& root, std::string const& name,
T&& value, std::string const& unit, uint8_t precision) const;
void addLiveViewText(JsonVariant& root, std::string const& name,
std::string const& text) const;
void addLiveViewWarning(JsonVariant& root, std::string const& name,
bool warning) const;
void addLiveViewAlarm(JsonVariant& root, std::string const& name,
bool alarm) const;

String _manufacturer = "unknown";
uint8_t _SoC = 0;
uint32_t _lastUpdateSoC = 0;
uint32_t _lastUpdate = 0;
};

class PylontechBatteryStats : public BatteryStats {
friend class PylontechCanReceiver;

public:
void getLiveViewData(JsonVariant& root) const final;
void mqttPublish() const final;

private:
void setManufacturer(String&& m) { _manufacturer = std::move(m); }
void setSoC(uint8_t SoC) { _SoC = SoC; _lastUpdateSoC = millis(); }
void setLastUpdate(uint32_t ts) { _lastUpdate = ts; }

float _chargeVoltage;
float _chargeCurrentLimitation;
float _dischargeCurrentLimitation;
uint16_t _stateOfHealth;
float _voltage; // total voltage of the battery pack
// total current into (positive) or from (negative)
// the battery, i.e., the charging current
float _current;
float _temperature;

bool _alarmOverCurrentDischarge;
bool _alarmOverCurrentCharge;
bool _alarmUnderTemperature;
bool _alarmOverTemperature;
bool _alarmUnderVoltage;
bool _alarmOverVoltage;
bool _alarmBmsInternal;

bool _warningHighCurrentDischarge;
bool _warningHighCurrentCharge;
bool _warningLowTemperature;
bool _warningHighTemperature;
bool _warningLowVoltage;
bool _warningHighVoltage;
bool _warningBmsInternal;

bool _chargeEnabled;
bool _dischargeEnabled;
bool _chargeImmediately;
};

class JkBmsBatteryStats : public BatteryStats {
public:
void getLiveViewData(JsonVariant& root) const final;
void mqttPublish() const final;

void updateFrom(JkBms::DataPointContainer const& dp);

private:
JkBms::DataPointContainer _dataPoints;
};
6 changes: 6 additions & 0 deletions include/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ struct CONFIG_T {
char Mqtt_ClientKey[MQTT_MAX_CERT_STRLEN +1];

bool Vedirect_Enabled;
bool Vedirect_VerboseLogging;
bool Vedirect_UpdatesOnly;

bool PowerMeter_Enabled;
Expand Down Expand Up @@ -166,6 +167,11 @@ struct CONFIG_T {
float PowerLimiter_FullSolarPassThroughStopVoltage;

bool Battery_Enabled;
bool Battery_VerboseLogging;
uint8_t Battery_Provider;
uint8_t Battery_JkBmsInterface;
uint8_t Battery_JkBmsPollingInterval;

bool Huawei_Enabled;
bool Huawei_Auto_Power_Enabled;
float Huawei_Auto_Power_Voltage_Limit;
Expand Down
75 changes: 75 additions & 0 deletions include/JkBmsController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#pragma once

#include <memory>
#include <vector>

#include "Battery.h"
#include "JkBmsSerialMessage.h"

class DataPointContainer;

namespace JkBms {

class Controller : public BatteryProvider {
public:
Controller() = default;

bool init(bool verboseLogging) final;
void deinit() final;
void loop() final;
std::shared_ptr<BatteryStats> getStats() const final { return _stats; }

private:
enum class Status : unsigned {
Initializing,
Timeout,
WaitingForPollInterval,
HwSerialNotAvailableForWrite,
BusyReading,
RequestSent,
FrameCompleted
};

std::string const& getStatusText(Status status);
void announceStatus(Status status);
void sendRequest(uint8_t pollInterval);
void rxData(uint8_t inbyte);
void reset();
void frameComplete();
void processDataPoints(DataPointContainer const& dataPoints);

enum class Interface : unsigned {
Invalid,
Uart,
Transceiver
};

Interface getInterface() const;

enum class ReadState : unsigned {
Idle,
WaitingForFrameStart,
FrameStartReceived,
StartMarkerReceived,
FrameLengthMsbReceived,
ReadingFrame
};
ReadState _readState;
void setReadState(ReadState state) {
_readState = state;
}

bool _verboseLogging = true;
int8_t _rxEnablePin = -1;
int8_t _txEnablePin = -1;
Status _lastStatus = Status::Initializing;
uint32_t _lastStatusPrinted = 0;
uint32_t _lastRequest = 0;
uint16_t _frameLength = 0;
uint8_t _protocolVersion = -1;
SerialResponse::tData _buffer = {};
std::shared_ptr<JkBmsBatteryStats> _stats =
std::make_shared<JkBmsBatteryStats>();
};

} /* namespace JkBms */
Loading

0 comments on commit 8dd96c4

Please sign in to comment.