currentMeas
This commit is contained in:
1 parent
f93a8aaabd
commit
d2b8e1de3c
9 files changed
+87
-22
No files matched your search
Vendored
+2
-2
@@ -11,9 +11,9 @@
|
|||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/build/src/sword/SwordMain",
|
"program": "${workspaceFolder}/build/src/sword/SwordMain",
|
||||||
"args": [
|
"args": [
|
||||||
//"test",
|
"promo", //"test",
|
||||||
"promo",
|
|
||||||
"${workspaceFolder}/assets",
|
"${workspaceFolder}/assets",
|
||||||
|
"-n", "SwordDebug",
|
||||||
"-b", "'mqtts://nerdyssey.de:8883'",
|
"-b", "'mqtts://nerdyssey.de:8883'",
|
||||||
"-t", "'staging/outdoor/king-arthur/sword/'",
|
"-t", "'staging/outdoor/king-arthur/sword/'",
|
||||||
"-p", "'awesomeexodusoutdooradventures'",
|
"-p", "'awesomeexodusoutdooradventures'",
|
||||||
|
|||||||
+1
-1
Submodule platform updated: 35a7eb5b40...6f6a0474cb.
@@ -23,3 +23,9 @@ Service to connect the Throne via MQTT
|
|||||||
|
|
||||||
Throne station
|
Throne station
|
||||||
Features Throne for final coronation
|
Features Throne for final coronation
|
||||||
|
|
||||||
|
## MQTT Testcommands
|
||||||
|
|
||||||
|
```sh
|
||||||
|
mosquitto_sub -h nerdyssey.de -p 8883 -t "staging/outdoor/king-arthur/#" -u "exodususer" -P "awesomeexodusoutdooradventures" --capath /etc/ssl/certs/ -d
|
||||||
|
```
|
||||||
Regular → Executable
+1
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
/home/gustice/workspace/swordStation/SwordMain \
|
/home/gustice/workspace/swordStation/SwordMain \
|
||||||
promo /home/gustice/workspace/swordStation/assets \
|
promo /home/gustice/workspace/swordStation/assets \
|
||||||
|
-n Sword \
|
||||||
-b mqtts://nerdyssey.de:8883 \
|
-b mqtts://nerdyssey.de:8883 \
|
||||||
-t outdoor/king-arthur/sword/ \
|
-t outdoor/king-arthur/sword/ \
|
||||||
-p awesomeexodusoutdooradventures \
|
-p awesomeexodusoutdooradventures \
|
||||||
|
|||||||
Regular → Executable
+1
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
/home/gustice/workspace/swordStation/SwordMain \
|
/home/gustice/workspace/swordStation/SwordMain \
|
||||||
test /home/gustice/workspace/swordStation/assets \
|
test /home/gustice/workspace/swordStation/assets \
|
||||||
|
-n SwordDebug \
|
||||||
-b mqtts://nerdyssey.de:8883 \
|
-b mqtts://nerdyssey.de:8883 \
|
||||||
-t staging/outdoor/king-arthur/sword/ \
|
-t staging/outdoor/king-arthur/sword/ \
|
||||||
-p awesomeexodusoutdooradventures \
|
-p awesomeexodusoutdooradventures \
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ add_executable(SwordMain swordMain.cpp)
|
|||||||
target_link_libraries(SwordMain
|
target_link_libraries(SwordMain
|
||||||
PkgConfig::LIBGPIOD
|
PkgConfig::LIBGPIOD
|
||||||
base
|
base
|
||||||
|
adc
|
||||||
palAdapt
|
palAdapt
|
||||||
loRa
|
loRa
|
||||||
os
|
os
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "swordMain.hpp"
|
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
|
#include "swordMain.hpp"
|
||||||
|
|
||||||
class MqttChannel {
|
class MqttChannel {
|
||||||
public:
|
public:
|
||||||
MqttChannel(string version, SwordConfig cfg, DeviceIoState& ioStat, SeqLogger& log)
|
MqttChannel(string name, string version, SwordConfig cfg, DeviceIoState& ioStat, SeqLogger& log)
|
||||||
: Config(cfg),
|
: Config(cfg),
|
||||||
IoStat(ioStat),
|
IoStat(ioStat),
|
||||||
Logger(log),
|
Logger(log),
|
||||||
@@ -35,9 +35,7 @@ class MqttChannel {
|
|||||||
{"promoDelay", ServiceCommands_e::SetConfigPromoDelay},
|
{"promoDelay", ServiceCommands_e::SetConfigPromoDelay},
|
||||||
}),
|
}),
|
||||||
subTopics{{runTopic, cfgTopic, resetTopic}},
|
subTopics{{runTopic, cfgTopic, resetTopic}},
|
||||||
client("Sword",
|
client(name, cfg.BrockerUrl, subTopics,
|
||||||
cfg.BrockerUrl,
|
|
||||||
subTopics,
|
|
||||||
{cfg.MqttUser, cfg.MqttPassword}) {
|
{cfg.MqttUser, cfg.MqttPassword}) {
|
||||||
fmt::println("MQTT: Starting task:");
|
fmt::println("MQTT: Starting task:");
|
||||||
mqttCall = [this](string topic, string payload) {
|
mqttCall = [this](string topic, string payload) {
|
||||||
@@ -86,7 +84,7 @@ class MqttChannel {
|
|||||||
fmt::println("Input queue flushed, {} Messages discarted", cnt);
|
fmt::println("Input queue flushed, {} Messages discarted", cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void runMasterService(Thread::Context& ctx, MqttChannel& instance, function<void()> resetCall) {
|
static void runMasterService(Thread::Context& ctx, MqttChannel& instance, function<void()> resetCall, CurrMon& mon) {
|
||||||
while (true) {
|
while (true) {
|
||||||
auto serMsg = instance.MasterQueue.dequeue();
|
auto serMsg = instance.MasterQueue.dequeue();
|
||||||
if (!serMsg) {
|
if (!serMsg) {
|
||||||
@@ -129,9 +127,21 @@ class MqttChannel {
|
|||||||
switch (code) {
|
switch (code) {
|
||||||
case ServiceCommands_e::SetLockOpen: {
|
case ServiceCommands_e::SetLockOpen: {
|
||||||
instance.IoStat.SwordLatch.moveIn();
|
instance.IoStat.SwordLatch.moveIn();
|
||||||
|
auto tE = std::chrono::steady_clock::now() + 6s;
|
||||||
|
while (std::chrono::steady_clock::now() < tE) {
|
||||||
|
Thread::sleep(100ms);
|
||||||
|
auto curr = mon.sampleCurrent();
|
||||||
|
}
|
||||||
|
auto currE = mon.sampleCurrent();
|
||||||
} break;
|
} break;
|
||||||
case ServiceCommands_e::SetLockClose: {
|
case ServiceCommands_e::SetLockClose: {
|
||||||
instance.IoStat.SwordLatch.moveOut();
|
instance.IoStat.SwordLatch.moveOut();
|
||||||
|
auto tE = std::chrono::steady_clock::now() + 6s;
|
||||||
|
while (std::chrono::steady_clock::now() < tE) {
|
||||||
|
Thread::sleep(100ms);
|
||||||
|
auto curr = mon.sampleCurrent();
|
||||||
|
}
|
||||||
|
auto currE = mon.sampleCurrent();
|
||||||
} break;
|
} break;
|
||||||
case ServiceCommands_e::PlaySoundPromo: {
|
case ServiceCommands_e::PlaySoundPromo: {
|
||||||
MediaPlayer::playWavFile(instance.Config.SoundPromo);
|
MediaPlayer::playWavFile(instance.Config.SoundPromo);
|
||||||
|
|||||||
+21
-10
@@ -8,9 +8,7 @@ using namespace std::literals::string_view_literals;
|
|||||||
using namespace std::literals::chrono_literals;
|
using namespace std::literals::chrono_literals;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
constexpr uint8_t VersionArr[4] = {'V', 0, 8, 0};
|
const string Version = "V 0.9.0";
|
||||||
const string Version = "V 0.8.0";
|
|
||||||
// const string Version = fmt::format("{} {}.{}.{}", VersionArr[0], VersionArr[1], VersionArr[2], VersionArr[3]);
|
|
||||||
|
|
||||||
unique_ptr<SwordConfig> SwordCfg;
|
unique_ptr<SwordConfig> SwordCfg;
|
||||||
unique_ptr<DeviceIoState> IoStat;
|
unique_ptr<DeviceIoState> IoStat;
|
||||||
@@ -21,6 +19,7 @@ void processProduction(MqttChannel& mqtt, SeqLogger& log);
|
|||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
CLI::App app{"Sword Firmware"};
|
CLI::App app{"Sword Firmware"};
|
||||||
|
string appName = "SwordDebug";
|
||||||
string modeArg = "test";
|
string modeArg = "test";
|
||||||
string assetsBasePath = "/home/user/assets/sword";
|
string assetsBasePath = "/home/user/assets/sword";
|
||||||
string brocker = "mqtts://nerdyssey.de:8883";
|
string brocker = "mqtts://nerdyssey.de:8883";
|
||||||
@@ -31,6 +30,7 @@ int main(int argc, char* argv[]) {
|
|||||||
string logApiKey = "uYpJC6WyZAbFK2MUgwNH";
|
string logApiKey = "uYpJC6WyZAbFK2MUgwNH";
|
||||||
app.add_option("startmode", modeArg, "Startup mode")->required();
|
app.add_option("startmode", modeArg, "Startup mode")->required();
|
||||||
app.add_option("basepath", assetsBasePath, "Base bath for assets")->required();
|
app.add_option("basepath", assetsBasePath, "Base bath for assets")->required();
|
||||||
|
app.add_option("-n,--name", appName, "Name of App");
|
||||||
app.add_option("-b,--brocker", brocker, "MQTT Topic URL");
|
app.add_option("-b,--brocker", brocker, "MQTT Topic URL");
|
||||||
app.add_option("-t,--topic", topic, "MQTT Topic");
|
app.add_option("-t,--topic", topic, "MQTT Topic");
|
||||||
app.add_option("-p,--passwd", password, "MQTT Brocker password");
|
app.add_option("-p,--passwd", password, "MQTT Brocker password");
|
||||||
@@ -40,7 +40,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
CLI11_PARSE(app, argc, argv);
|
CLI11_PARSE(app, argc, argv);
|
||||||
|
|
||||||
SeqLogger log(logUrl, logApiKey, "Sword");
|
SeqLogger log(logUrl, logApiKey, appName);
|
||||||
SwordCfg = make_unique<SwordConfig>(assetsBasePath, brocker, topic, user, password);
|
SwordCfg = make_unique<SwordConfig>(assetsBasePath, brocker, topic, user, password);
|
||||||
|
|
||||||
fmt::println("{}", app.get_description());
|
fmt::println("{}", app.get_description());
|
||||||
@@ -78,15 +78,23 @@ int main(int argc, char* argv[]) {
|
|||||||
InputTransAware SwordPulled(spPort);
|
InputTransAware SwordPulled(spPort);
|
||||||
LinMot SwordLatch(mOut1, mOut2);
|
LinMot SwordLatch(mOut1, mOut2);
|
||||||
|
|
||||||
|
I2cMaster i2cDev(II2cMaster::ClockRate::_400k);
|
||||||
|
AdcAds1115 adc(i2cDev, AdcAds1115::I2CAddress::Gnd);
|
||||||
|
// Check if the ADC is connected
|
||||||
|
if (!adc.isConnected()) {
|
||||||
|
fmt::println("Failed to connect ot Sensor {}", modeArg);
|
||||||
|
}
|
||||||
|
CurrMon mon(adc);
|
||||||
|
|
||||||
IoStat = make_unique<DeviceIoState>(SwordEntry, SwordEnd, SwordPulled, SwordLatch);
|
IoStat = make_unique<DeviceIoState>(SwordEntry, SwordEnd, SwordPulled, SwordLatch);
|
||||||
|
|
||||||
MqttChannel mqtt(Version, *SwordCfg, *IoStat, log);
|
MqttChannel mqtt(appName, Version, *SwordCfg, *IoStat, log);
|
||||||
auto resetCall = [&]() {
|
auto resetCall = [&]() {
|
||||||
log.sendEvent("Reset", "");
|
log.sendEvent("Reset", "");
|
||||||
};
|
};
|
||||||
|
|
||||||
mqtt.flushInput();
|
mqtt.flushInput();
|
||||||
static auto conTask = Thread::createExplicit("MqttTask", MqttChannel::runMasterService, ref(mqtt), resetCall);
|
static auto conTask = Thread::createExplicit("MqttTask", MqttChannel::runMasterService, ref(mqtt), resetCall, ref(mon));
|
||||||
|
|
||||||
SwordLatch.moveOut();
|
SwordLatch.moveOut();
|
||||||
fmt::println("Running App");
|
fmt::println("Running App");
|
||||||
@@ -128,12 +136,14 @@ void processPromo(MqttChannel& mqtt, SeqLogger& log) {
|
|||||||
Tick tmu(1min);
|
Tick tmu(1min);
|
||||||
Tick tn(1s);
|
Tick tn(1s);
|
||||||
Tick tsf(30min);
|
Tick tsf(30min);
|
||||||
|
Waiter dP;
|
||||||
auto& serCmds = mqtt.getSerCommands();
|
auto& serCmds = mqtt.getSerCommands();
|
||||||
while (true) {
|
while (true) {
|
||||||
Thread::sleep(10ms);
|
Thread::sleep(10ms);
|
||||||
IoStat->tick();
|
IoStat->tick();
|
||||||
if (IoStat->SwordPulled.isPosEdge()) {
|
if (IoStat->SwordPulled.isPosEdge()) {
|
||||||
if (!IoStat->Mute) {
|
if (!IoStat->Mute) {
|
||||||
|
if (dP.tick(IoStat->PromoDelay)) {
|
||||||
log.sendEvent("Pull", "Start Audio");
|
log.sendEvent("Pull", "Start Audio");
|
||||||
|
|
||||||
if (tsf.tick()) {
|
if (tsf.tick()) {
|
||||||
@@ -141,10 +151,11 @@ void processPromo(MqttChannel& mqtt, SeqLogger& log) {
|
|||||||
} else {
|
} else {
|
||||||
MediaPlayer::playWavFile(SwordCfg->SoundPromoShort);
|
MediaPlayer::playWavFile(SwordCfg->SoundPromoShort);
|
||||||
}
|
}
|
||||||
|
dP.sample();
|
||||||
fmt::println("Waiting for {}", IoStat->PromoDelay);
|
fmt::println("Muting next for {}", IoStat->PromoDelay);
|
||||||
Thread::sleep(IoStat->PromoDelay);
|
} else {
|
||||||
fmt::println("Waiting done");
|
fmt::println("still muted");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tn.tick()) {
|
if (tn.tick()) {
|
||||||
|
|||||||
+38
-3
@@ -20,9 +20,11 @@
|
|||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Ads1115.hpp"
|
||||||
#include "MqttClient.hpp"
|
#include "MqttClient.hpp"
|
||||||
#include "coreExcept.hpp"
|
#include "coreExcept.hpp"
|
||||||
#include "gpioPort.hpp"
|
#include "gpioPort.hpp"
|
||||||
|
#include "i2cPort.hpp"
|
||||||
#include "logging.hpp"
|
#include "logging.hpp"
|
||||||
#include "queue.hpp"
|
#include "queue.hpp"
|
||||||
#include "textUtils.hpp"
|
#include "textUtils.hpp"
|
||||||
@@ -50,6 +52,39 @@ class LinMot {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CurrMon {
|
||||||
|
// https://www.monolithicpower.com/en/documentview/productdocument/index/version/2/document_type/Datasheet/lang/EN/sku/MCS1802/document_id/5066/
|
||||||
|
public:
|
||||||
|
CurrMon(AdcAds1115& adc)
|
||||||
|
: _adc(adc) {
|
||||||
|
adc.setPga(AdcAds1115::Pga::FSR_4_096V);
|
||||||
|
adc.startContinuousConversion();
|
||||||
|
|
||||||
|
float val{};
|
||||||
|
for (size_t i = 0; i < 8; i++) {
|
||||||
|
val += sampe();
|
||||||
|
}
|
||||||
|
_refVal = val / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sampleCurrent() {
|
||||||
|
auto val = sampe() - _refVal;
|
||||||
|
val = val / 0.264;
|
||||||
|
fmt::println("{:.2} A", val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _refVal{};
|
||||||
|
AdcAds1115& _adc;
|
||||||
|
|
||||||
|
float sampe() {
|
||||||
|
float volt;
|
||||||
|
_adc.readConversionVoltage(volt);
|
||||||
|
return volt;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class DeviceIoState {
|
class DeviceIoState {
|
||||||
public:
|
public:
|
||||||
DeviceIoState(pal::InputTransAware& entry,
|
DeviceIoState(pal::InputTransAware& entry,
|
||||||
@@ -75,7 +110,7 @@ class DeviceIoState {
|
|||||||
|
|
||||||
std::chrono::seconds PromoDelay{150};
|
std::chrono::seconds PromoDelay{150};
|
||||||
int Volume{50};
|
int Volume{50};
|
||||||
bool Mute{false};
|
bool Mute{true};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SwordConfig {
|
struct SwordConfig {
|
||||||
@@ -113,7 +148,7 @@ class MediaPlayer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
thread audioThread([filePath]() {
|
thread audioThread([filePath]() {
|
||||||
auto cmd = fmt::format("aplay '{}' 2>/dev/null", filePath);
|
auto cmd = fmt::format("aplay '{}'", filePath);
|
||||||
auto result = system(cmd.c_str());
|
auto result = system(cmd.c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
fmt::println(stderr, "ERROR: Failed to play audio file: '{}'", filePath);
|
fmt::println(stderr, "ERROR: Failed to play audio file: '{}'", filePath);
|
||||||
@@ -134,7 +169,7 @@ class MediaPlayer {
|
|||||||
fmt::println(stderr, "ERROR: No ALSA volume control found");
|
fmt::println(stderr, "ERROR: No ALSA volume control found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto cmd = fmt::format("amixer -q sset '{}' {}% 2>/dev/null", control, volume);
|
auto cmd = fmt::format("amixer -q sset '{}' {}%", control, volume);
|
||||||
auto result = system(cmd.c_str());
|
auto result = system(cmd.c_str());
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
fmt::println(stderr, "ERROR: Failed to set volume to {}%", volume);
|
fmt::println(stderr, "ERROR: Failed to set volume to {}%", volume);
|
||||||
|
|||||||
Reference in new issue
Block a user