diff options
author | Evgeny Zinoviev <me@ch1p.io> | 2021-05-07 02:18:07 +0300 |
---|---|---|
committer | Evgeny Zinoviev <me@ch1p.io> | 2021-05-07 02:18:07 +0300 |
commit | 7e743b73433475df086fcec81be7b10c1d695a42 (patch) | |
tree | 1737c5f9bdad2a40f740e9a655e510641331b9e2 /src/inverterd.cc |
initial
Diffstat (limited to 'src/inverterd.cc')
-rw-r--r-- | src/inverterd.cc | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/inverterd.cc b/src/inverterd.cc new file mode 100644 index 0000000..1357454 --- /dev/null +++ b/src/inverterd.cc @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: BSD-3-Clause + +#include <iostream> +#include <string> +#include <vector> +#include <iomanip> +#include <ios> +#include <getopt.h> + +#include "common.h" +#include "voltronic/device.h" +#include "voltronic/exceptions.h" +#include "p18/exceptions.h" +#include "util.h" +#include "logging.h" +#include "server/server.h" +#include "server/signal.h" + +static const char* DEFAULT_HOST = "127.0.0.1"; +static int DEFAULT_PORT = 8305; + +static void usage(const char* progname) { + std::cout << "Usage: " << progname << " OPTIONS [COMMAND]\n" << + "\n" + "Options:\n" + " -h, --help: Show this help\n" + " --host <HOST>: Server host (default: " << DEFAULT_HOST << ")\n" + " --port <PORT> Server port (default: " << DEFAULT_PORT << ")\n" + " --device <DEVICE>: 'usb' (default), 'serial' or 'pseudo'\n" + " --timeout <TIMEOUT>: Device timeout in ms (default: " << voltronic::Device::TIMEOUT << ")\n" + " --cache-timeout <TIMEOUT>" + " Cache validity time, in ms (default: " << server::Server::CACHE_TIMEOUT << ")\n" + " --verbose: Be verbose\n" + "\n"; + + std::ios_base::fmtflags f(std::cout.flags()); + std::cout << std::hex << std::setfill('0') << + "USB device options:\n" + " --usb-vendor-id <ID>: Vendor ID (default: " << std::setw(4) << voltronic::USBDevice::VENDOR_ID << ")\n" + " --usb-device-id <ID>: Device ID (default: " << std::setw(4) << voltronic::USBDevice::PRODUCT_ID << ")\n"; + std::cout.flags(f); + + std::cout << "\n" + "Serial device options:\n" + " --serial-name <NAME>: Path to serial device (default: " << voltronic::SerialDevice::DEVICE_NAME << ")\n" + " --serial-baud-rate 110|300|1200|2400|4800|9600|19200|38400|57600|115200\n" + " --serial-data-bits 5|6|7|8\n" + " --serial-stop-bits 1|1.5|2\n" + " --serial-parity none|odd|even|mark|space\n"; + exit(1); +} + + +int main(int argc, char *argv[]) { + // common params + uint64_t timeout = voltronic::Device::TIMEOUT; + uint64_t cacheTimeout = server::Server::CACHE_TIMEOUT; + bool verbose = false; + + // server params + std::string host(DEFAULT_HOST); + int port = DEFAULT_PORT; + + // device params + DeviceType deviceType = DeviceType::USB; + + unsigned short usbVendorId = voltronic::USBDevice::VENDOR_ID; + unsigned short usbDeviceId = voltronic::USBDevice::PRODUCT_ID; + + std::string serialDeviceName(voltronic::SerialDevice::DEVICE_NAME); + voltronic::SerialBaudRate serialBaudRate = voltronic::SerialDevice::BAUD_RATE; + voltronic::SerialDataBits serialDataBits = voltronic::SerialDevice::DATA_BITS; + voltronic::SerialStopBits serialStopBits = voltronic::SerialDevice::STOP_BITS; + voltronic::SerialParity serialParity = voltronic::SerialDevice::PARITY; + + try { + int opt; + struct option long_options[] = { + {"help", no_argument, nullptr, 'h'}, + {"verbose", no_argument, nullptr, LO_VERBOSE}, + {"timeout", required_argument, nullptr, LO_TIMEOUT}, + {"cache-timeout", required_argument, nullptr, LO_CACHE_TIMEOUT}, + {"device", required_argument, nullptr, LO_DEVICE}, + {"usb-vendor-id", required_argument, nullptr, LO_USB_VENDOR_ID}, + {"usb-device-id", required_argument, nullptr, LO_USB_DEVICE_ID}, + {"serial-name", required_argument, nullptr, LO_SERIAL_NAME}, + {"serial-baud-rate", required_argument, nullptr, LO_SERIAL_BAUD_RATE}, + {"serial-data-bits", required_argument, nullptr, LO_SERIAL_DATA_BITS}, + {"serial-stop-bits", required_argument, nullptr, LO_SERIAL_STOP_BITS}, + {"serial-parity", required_argument, nullptr, LO_SERIAL_PARITY}, + {"host", required_argument, nullptr, LO_HOST}, + {"port", required_argument, nullptr, LO_PORT}, + {nullptr, 0, nullptr, 0} + }; + + bool getoptError = false; // FIXME + while ((opt = getopt_long(argc, argv, "h", long_options, nullptr)) != EOF) { + if (opt == '?') { + getoptError = true; + break; + } + + // simple options (flags), no arguments + switch (opt) { + case 'h': + usage(argv[0]); + + case LO_VERBOSE: + verbose = true; + continue; + + default: + break; + } + + // options with arguments + std::string arg; + if (optarg) + arg = std::string(optarg); + + switch (opt) { + case LO_DEVICE: + if (arg == "usb") + deviceType = DeviceType::USB; + else if (arg == "serial") + deviceType = DeviceType::Serial; + else if (arg == "pseudo") + deviceType = DeviceType::Pseudo; + else + throw std::invalid_argument("invalid device"); + + break; + + case LO_TIMEOUT: + timeout = std::stoull(arg); + break; + + case LO_CACHE_TIMEOUT: + cacheTimeout = std::stoull(arg); + break; + + case LO_USB_VENDOR_ID: + try { + if (arg.size() != 4) + throw std::invalid_argument("usb-vendor-id: invalid length"); + usbVendorId = static_cast<unsigned short>(hextoul(arg)); + } catch (std::invalid_argument& e) { + throw std::invalid_argument(std::string("usb-vendor-id: invalid format: ") + e.what()); + } + break; + + case LO_USB_DEVICE_ID: + try { + if (arg.size() != 4) + throw std::invalid_argument("usb-device-id: invalid length"); + usbDeviceId = static_cast<unsigned short>(hextoul(arg)); + } catch (std::invalid_argument& e) { + throw std::invalid_argument(std::string("usb-device-id: invalid format: ") + e.what()); + } + break; + + case LO_SERIAL_NAME: + serialDeviceName = arg; + break; + + case LO_SERIAL_BAUD_RATE: + serialBaudRate = static_cast<voltronic::SerialBaudRate>(std::stoul(arg)); + if (!voltronic::is_serial_baud_rate_valid(serialBaudRate)) + throw std::invalid_argument("invalid serial baud rate"); + break; + + case LO_SERIAL_DATA_BITS: + serialDataBits = static_cast<voltronic::SerialDataBits>(std::stoul(arg)); + if (voltronic::is_serial_data_bits_valid(serialDataBits)) + throw std::invalid_argument("invalid serial data bits"); + break; + + case LO_SERIAL_STOP_BITS: + if (arg == "1") + serialStopBits = voltronic::SerialStopBits::One; + else if (arg == "1.5") + serialStopBits = voltronic::SerialStopBits::OneAndHalf; + else if (arg == "2") + serialStopBits = voltronic::SerialStopBits::Two; + else + throw std::invalid_argument("invalid serial stop bits"); + break; + + case LO_SERIAL_PARITY: + if (arg == "none") + serialParity = voltronic::SerialParity::None; + else if (arg == "odd") + serialParity = voltronic::SerialParity::Odd; + else if (arg == "even") + serialParity = voltronic::SerialParity::Even; + else if (arg == "mark") + serialParity = voltronic::SerialParity::Mark; + else if (arg == "space") + serialParity = voltronic::SerialParity::Space; + else + throw std::invalid_argument("invalid serial parity"); + break; + + case LO_HOST: + host = arg; + break; + + case LO_PORT: + port = std::stoi(arg); + break; + + default: + break; + } + } + + if (optind < argc) + throw std::invalid_argument("extra parameter found"); + } catch (std::invalid_argument& e) { + myerr << "error: " << e.what(); + return 1; + } + + // open device + std::shared_ptr<voltronic::Device> dev; + try { + switch (deviceType) { + case DeviceType::USB: + dev = std::shared_ptr<voltronic::Device>(new voltronic::USBDevice(usbVendorId, usbDeviceId)); + break; + + case DeviceType::Pseudo: + dev = std::shared_ptr<voltronic::Device>(new voltronic::PseudoDevice); + break; + + case DeviceType::Serial: + dev = std::shared_ptr<voltronic::Device>(new voltronic::SerialDevice(serialDeviceName, + serialBaudRate, + serialDataBits, + serialStopBits, + serialParity)); + break; + } + + dev->setTimeout(timeout); + +// p18::Client client; +// client.setDevice(dev); + + /*if (action == Action::Raw) { + auto result = client.runOnDevice(raw); + if (verbose) + std::cerr << hexdump(result.first.get(), result.second); + std::cout << std::string(result.first.get(), result.second) << std::endl; + } else { + auto response = client.execute(commandType, arguments); + std::cout << *(response->format(format).get()) << std::endl; + }*/ + +// success = true; + } + catch (voltronic::DeviceError& e) { + myerr << "device error: " << e.what(); + return 1; + } + catch (voltronic::TimeoutError& e) { + myerr << "timeout error: " << e.what(); + return 1; + } + catch (voltronic::InvalidDataError& e) { + myerr << "data is invalid: " << e.what(); + return 1; + } + catch (p18::InvalidResponseError& e) { + myerr << "response is invalid: " << e.what(); + return 1; + } + + // create server + server::set_signal_handlers(); + + server::Server server(dev); + server.setVerbose(verbose); + server.setCacheTimeout(cacheTimeout); + + server.start(host, port); + + if (verbose) + mylog << "done"; + + return 0; +}
\ No newline at end of file |