Skip to content

Commit

Permalink
Initial upload of all my changes
Browse files Browse the repository at this point in the history
  • Loading branch information
nrm21 committed Feb 20, 2018
1 parent 0dcc6c0 commit 0e0a7f8
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 74 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
out/
test/
34 changes: 34 additions & 0 deletions inputparser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// @author iain

#include <algorithm>
#include <string>
#include <vector>
#include "inputparser.h"

// This class simply finds cmd line args and parses them for use in a program.
// It is not posix compliant and wont work with args like: ./program -xf filename
// You must place each arg after its own seperate dash like: ./program -x -f filename

InputParser::InputParser (int &argc, char **argv)
{
for (int i=1; i < argc; ++i)
this->tokens.push_back(std::string(argv[i]));
}
const std::string& InputParser::getCmdOption(const std::string &option) const
{
std::vector<std::string>::const_iterator itr;
itr = std::find(this->tokens.begin(), this->tokens.end(), option);
if (itr != this->tokens.end() && ++itr != this->tokens.end())
{
return *itr;
}
static const std::string empty_string("");
return empty_string;
}
bool InputParser::cmdOptionExists(const std::string &option) const
{
return std::find(this->tokens.begin(), this->tokens.end(), option)
!= this->tokens.end();
}

std::vector <std::string> tokens;
18 changes: 18 additions & 0 deletions inputparser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// inputparser.h
// @author iain
#ifndef INPUTPARSER_H
#define INPUTPARSER_H

#include <vector>

class InputParser
{
std::vector <std::string> tokens;

public:
InputParser (int &argc, char **argv);
const std::string& getCmdOption(const std::string &option) const;
bool cmdOptionExists(const std::string &option) const;
};

#endif // ___INPUTPARSER_H
153 changes: 123 additions & 30 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include <algorithm>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <thread>
#include "main.h"
#include "inputparser.h"
#include "tools.h"

#include <pthread.h>
Expand All @@ -11,76 +14,166 @@
cSkymax *ups = NULL;
atomic_bool ups_status_changed(false);
atomic_bool ups_data_changed(false);
atomic_bool ups_cmd_executed(false);

int main()
int print_help()
{
printf("USAGE: skymax -d <device ex: /dev/hidraw0> [-i <run interval> | -r <raw command>] [-h | --help]\n\n");
return 1;
}

int main(int argc, char** argv)
{
float voltage_grid;
float freq_grid;
float voltage_out;
float freq_out;

int load_va;
int load_watt;
int load_percent;
int voltage_bus;

float voltage_batt;
int batt_charge_current;
int batt_capacity;
int temp_heatsink;
int pv1;
float pv2;
int pv_input_current;
float pv_input_voltage;
float pv_input_watts;
float pv_input_watthour;
float load_watthour = 0;
float scc;
int batt_discharge_current;

InputParser cmdArgs(argc, argv);
// Get (non-optional) device to read (probably /dev/hidraw0 or /dev/hidraw1)
const std::string& devicename = cmdArgs.getCmdOption("-d");
const std::string& rawcmd = cmdArgs.getCmdOption("-r");
const std::string& runinterval = cmdArgs.getCmdOption("-i");

if(cmdArgs.cmdOptionExists("-h") || cmdArgs.cmdOptionExists("--help"))
{
return print_help();
}

if (devicename.empty())
{
printf("Device must be provided.\n");
return print_help();
}

// Now get EITHER '-r' if we are executing a command.
if(cmdArgs.cmdOptionExists("-r"))
{
if (rawcmd.empty())
{
printf("raw command must be provided.\n");
return print_help();
}
}
else // OR get '-i' if we are polling instead.
{
// Check run interval for correctness
if (runinterval.empty())
{
printf("Run interval must be provided.\n");
return print_help();
}
else
{
bool has_only_digits = true;
for (size_t n = 0; n < runinterval.length(); n++)
{
if (!isdigit(runinterval[n]))
{
has_only_digits = false;
break;
}
}

if (!has_only_digits)
{
printf("Run interval must be all digits.\n");
return 0;
}
}
}

bool ups_status_changed(false);
ups = new cSkymax;
ups = new cSkymax(devicename);

if (!rawcmd.empty())
{
ups->ExecuteCmd(rawcmd);
printf("Reply: %s\n", ups->GetStatus()->c_str());
goto endloop;
}

ups->runMultiThread();

lprintf("MAIN LOOP");
while (true)
{
// If inverter mode changes print it to screen
if (ups_status_changed)
{
string *mode = ups->GetMode();
int mode = ups->GetMode();
if (mode)
{
lprintf("SKYMAX: %s", mode->c_str());
delete mode;
}
lprintf("SKYMAX: %d", mode);
ups_status_changed = false;
}


// If we recieve QPIGs data print it to screen
if (ups_data_changed)
{
ups_data_changed = false;


int mode = ups->GetMode();
string *reply = ups->GetStatus();
if (reply)
{
//parse and display values
sscanf(reply->c_str(), "%f %f %f %f %d %d %d %d %f %d %d %d %d %f %f %d", &voltage_grid, &freq_grid, &voltage_out, &freq_out, &load_va, &load_watt, &load_percent, &voltage_bus, &voltage_batt, &batt_charge_current, &batt_capacity, &temp_heatsink, &pv1, &pv2, &scc, &batt_discharge_current);
printf("\tAC Grid voltage: %.1f\n", voltage_grid);
printf("\tAC Grid frequency: %.1f\n", freq_grid);
printf("\tAC out voltage: %.1f\n", voltage_out);
printf("\tAC out frequency: %.1f\n", freq_out);
printf("\tLoad [%]: %d\n", load_percent);
printf("\tLoad [W]: %d\n", load_watt);
printf("\tLoad [VA]: %d\n", load_va);
printf("\tBus voltage: %d\n", voltage_bus);
printf("\tHeatsink temperature: %d\n", temp_heatsink);
printf("\tBattery capacity [%]: %d\n", batt_capacity);
printf("\tBattery voltage: %.2f\n", voltage_batt);
printf("\tBattery charge current [A]: %d\n", batt_charge_current);
printf("\tBattery discharge current [A]: %d\n", batt_discharge_current);
// Parse and display values
sscanf(reply->c_str(), "%f %f %f %f %d %d %d %d %f %d %d %d %d %f %f %d", &voltage_grid, &freq_grid, &voltage_out, &freq_out, &load_va, &load_watt, &load_percent, &voltage_bus, &voltage_batt, &batt_charge_current, &batt_capacity, &temp_heatsink, &pv_input_current, &pv_input_voltage, &scc, &batt_discharge_current);

// Calculate wattage (assume 92% efficiency)
pv_input_watts = (pv_input_voltage * pv_input_current) * .92;
// Calculate watthours generated per run interval period (given as program argument)
pv_input_watthour = pv_input_watts / (3600 / stoi(runinterval.data()));
// Only calculate load watthours if we are in battery mode (line mode doesn't count towards money savings)
if (mode == 4)
load_watthour = (float)load_watt / (3600 / stoi(runinterval.data()));

// Print as JSON
printf("{\n");
printf("\"Inverter_mode\":%d,\n", mode);
printf("\"AC_grid_voltage\":%.1f,\n", voltage_grid);
printf("\"AC_grid_frequency\":%.1f,\n", freq_grid);
printf("\"AC_out_voltage\":%.1f,\n", voltage_out);
printf("\"AC_out_frequency\":%.1f,\n", freq_out);
printf("\"PV_in_voltage\":%.1f,\n", pv_input_voltage);
printf("\"PV_in_current\":%d,\n", pv_input_current);
printf("\"PV_in_watts\":%.1f,\n", pv_input_watts);
printf("\"PV_in_watthour\":%.4f,\n", pv_input_watthour);
printf("\"Load_pct\":%d,\n", load_percent);
printf("\"Load_watt\":%d,\n", load_watt);
printf("\"Load_watthour\":%.4f,\n", load_watthour);
printf("\"Load_va\":%d,\n", load_va);
printf("\"Bus_voltage\":%d,\n", voltage_bus);
printf("\"Heatsink_temperature\":%d,\n", temp_heatsink);
printf("\"Battery_capacity\":%d,\n", batt_capacity);
printf("\"Battery_voltage\":%.2f,\n", voltage_batt);
printf("\"Battery_charge_current\":%d,\n", batt_charge_current);
printf("\"Battery_discharge_current\":%d\n", batt_discharge_current);
printf("}\n");

delete reply;

// Do once and exit instead of loop endlessly
goto endloop;
}
}

sleep(1);
}
lprintf("MAIN LOOP END");
endloop:

if (ups)
delete ups;
Expand Down
Loading

0 comments on commit 0e0a7f8

Please sign in to comment.