Initial re-upload of spice2x-24-08-24
This commit is contained in:
4
api/resources/arduino/README.md
Normal file
4
api/resources/arduino/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# SpiceAPI Arduino Library
|
||||
This library is still a bit experimental and might contain bugs.
|
||||
|
||||
To use this library, it's recommended to just copy the Arduino project and start from that.
|
||||
169
api/resources/arduino/spiceapi/connection.h
Normal file
169
api/resources/arduino/spiceapi/connection.h
Normal file
@@ -0,0 +1,169 @@
|
||||
#ifndef SPICEAPI_CONNECTION_H
|
||||
#define SPICEAPI_CONNECTION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rc4.h"
|
||||
|
||||
#ifndef SPICEAPI_INTERFACE
|
||||
#define SPICEAPI_INTERFACE Serial
|
||||
#endif
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
class Connection {
|
||||
private:
|
||||
uint8_t* receive_buffer;
|
||||
size_t receive_buffer_size;
|
||||
const char* password;
|
||||
RC4* cipher;
|
||||
|
||||
public:
|
||||
Connection(size_t receive_buffer_size, const char* password = "");
|
||||
~Connection();
|
||||
|
||||
void reset();
|
||||
|
||||
bool check();
|
||||
void cipher_alloc(const char *session_key = nullptr);
|
||||
void change_pass(const char* password, bool session = false);
|
||||
const char* request(const char* json, size_t timeout = 1000);
|
||||
const char* request(char* json, size_t timeout = 1000);
|
||||
};
|
||||
}
|
||||
|
||||
spiceapi::Connection::Connection(size_t receive_buffer_size, const char* password) {
|
||||
this->receive_buffer = new uint8_t[receive_buffer_size];
|
||||
this->receive_buffer_size = receive_buffer_size;
|
||||
this->password = password;
|
||||
this->cipher = nullptr;
|
||||
this->reset();
|
||||
}
|
||||
|
||||
spiceapi::Connection::~Connection() {
|
||||
|
||||
// clean up
|
||||
if (this->cipher != nullptr)
|
||||
delete this->cipher;
|
||||
}
|
||||
|
||||
void spiceapi::Connection::reset() {
|
||||
|
||||
// drop all input
|
||||
while (SPICEAPI_INTERFACE.available()) {
|
||||
SPICEAPI_INTERFACE.read();
|
||||
}
|
||||
|
||||
#ifdef SPICEAPI_INTERFACE_WIFICLIENT
|
||||
// reconnect TCP client
|
||||
SPICEAPI_INTERFACE.stop();
|
||||
this->check();
|
||||
#else
|
||||
// 8 zeroes reset the password/session on serial
|
||||
for (size_t i = 0; i < 8; i++) {
|
||||
SPICEAPI_INTERFACE.write((int) 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// reset password
|
||||
this->cipher_alloc();
|
||||
}
|
||||
|
||||
void spiceapi::Connection::cipher_alloc(const char *session_key) {
|
||||
|
||||
// delete old cipher
|
||||
if (this->cipher != nullptr) {
|
||||
delete this->cipher;
|
||||
this->cipher = nullptr;
|
||||
}
|
||||
|
||||
// create new cipher if password is set
|
||||
session_key = session_key ? session_key : this->password;
|
||||
if (strlen(session_key) > 0) {
|
||||
this->cipher = new RC4(
|
||||
(uint8_t *) session_key,
|
||||
strlen(session_key));
|
||||
}
|
||||
}
|
||||
|
||||
bool spiceapi::Connection::check() {
|
||||
#ifdef SPICEAPI_INTERFACE_WIFICLIENT
|
||||
if (!SPICEAPI_INTERFACE.connected()) {
|
||||
return SPICEAPI_INTERFACE.connect(
|
||||
SPICEAPI_INTERFACE_WIFICLIENT_HOST,
|
||||
SPICEAPI_INTERFACE_WIFICLIENT_PORT);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// serial is always valid
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void spiceapi::Connection::change_pass(const char* password, bool session) {
|
||||
if (!session) {
|
||||
this->password = password;
|
||||
}
|
||||
this->cipher_alloc(password);
|
||||
}
|
||||
|
||||
const char* spiceapi::Connection::request(const char* json, size_t timeout) {
|
||||
auto json_len = strlen(json);
|
||||
strncpy((char*) receive_buffer, json, receive_buffer_size);
|
||||
return request((char*) receive_buffer, timeout);
|
||||
}
|
||||
|
||||
const char* spiceapi::Connection::request(char* json_data, size_t timeout) {
|
||||
|
||||
// check connection
|
||||
if (!this->check())
|
||||
return "";
|
||||
|
||||
// crypt
|
||||
auto json_len = strlen(json_data) + 1;
|
||||
if (this->cipher != nullptr)
|
||||
this->cipher->crypt((uint8_t*) json_data, json_len);
|
||||
|
||||
// send
|
||||
auto send_result = SPICEAPI_INTERFACE.write((const char*) json_data, (int) json_len);
|
||||
SPICEAPI_INTERFACE.flush();
|
||||
if (send_result < (int) json_len) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// receive
|
||||
size_t receive_data_len = 0;
|
||||
auto t_start = millis();
|
||||
while (SPICEAPI_INTERFACE) {
|
||||
|
||||
// check for timeout
|
||||
if (millis() - t_start > timeout) {
|
||||
this->reset();
|
||||
return "";
|
||||
}
|
||||
|
||||
// read single byte
|
||||
auto b = SPICEAPI_INTERFACE.read();
|
||||
if (b < 0) continue;
|
||||
receive_buffer[receive_data_len++] = b;
|
||||
|
||||
// check for buffer overflow
|
||||
if (receive_data_len >= receive_buffer_size) {
|
||||
this->reset();
|
||||
return "";
|
||||
}
|
||||
|
||||
// crypt
|
||||
if (this->cipher != nullptr)
|
||||
this->cipher->crypt(&receive_buffer[receive_data_len - 1], 1);
|
||||
|
||||
// check for message end
|
||||
if (receive_buffer[receive_data_len - 1] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// return resulting json
|
||||
return (const char*) &receive_buffer[0];
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_CONNECTION_H
|
||||
65
api/resources/arduino/spiceapi/rc4.h
Normal file
65
api/resources/arduino/spiceapi/rc4.h
Normal file
@@ -0,0 +1,65 @@
|
||||
#ifndef SPICEAPI_RC4_H
|
||||
#define SPICEAPI_RC4_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
class RC4 {
|
||||
private:
|
||||
uint8_t s_box[256];
|
||||
size_t a = 0, b = 0;
|
||||
|
||||
public:
|
||||
|
||||
RC4(uint8_t *key, size_t key_size);
|
||||
|
||||
void crypt(uint8_t *data, size_t size);
|
||||
};
|
||||
}
|
||||
|
||||
spiceapi::RC4::RC4(uint8_t *key, size_t key_size) {
|
||||
|
||||
// initialize S-BOX
|
||||
for (size_t i = 0; i < sizeof(s_box); i++)
|
||||
s_box[i] = (uint8_t) i;
|
||||
|
||||
// check key size
|
||||
if (!key_size)
|
||||
return;
|
||||
|
||||
// KSA
|
||||
size_t j = 0;
|
||||
for (size_t i = 0; i < sizeof(s_box); i++) {
|
||||
|
||||
// update
|
||||
j = (j + s_box[i] + key[i % key_size]) % sizeof(s_box);
|
||||
|
||||
// swap
|
||||
auto tmp = s_box[i];
|
||||
s_box[i] = s_box[j];
|
||||
s_box[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
void spiceapi::RC4::crypt(uint8_t *data, size_t size) {
|
||||
|
||||
// iterate all bytes
|
||||
for (size_t pos = 0; pos < size; pos++) {
|
||||
|
||||
// update
|
||||
a = (a + 1) % sizeof(s_box);
|
||||
b = (b + s_box[a]) % sizeof(s_box);
|
||||
|
||||
// swap
|
||||
auto tmp = s_box[a];
|
||||
s_box[a] = s_box[b];
|
||||
s_box[b] = tmp;
|
||||
|
||||
// crypt
|
||||
data[pos] ^= s_box[(s_box[a] + s_box[b]) % sizeof(s_box)];
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_RC4_H
|
||||
172
api/resources/arduino/spiceapi/spiceapi.ino
Normal file
172
api/resources/arduino/spiceapi/spiceapi.ino
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* SpiceAPI Arduino Example Project
|
||||
*
|
||||
* To enable it in SpiceTools, use "-api 1337 -apipass changeme -apiserial COM1" or similar.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SpiceAPI Wrapper Buffer Sizes
|
||||
*
|
||||
* They should be as big as possible to be able to create/parse
|
||||
* some of the bigger requests/responses. Due to dynamic memory
|
||||
* limitations of some weaker devices, if you set them too high
|
||||
* you will probably experience crashes/bugs/problems, one
|
||||
* example would be "Request ID is invalid" in the log.
|
||||
*/
|
||||
#define SPICEAPI_WRAPPER_BUFFER_SIZE 256
|
||||
#define SPICEAPI_WRAPPER_BUFFER_SIZE_STR 256
|
||||
|
||||
/*
|
||||
* WiFi Support
|
||||
* Uncomment to enable the wireless API interface.
|
||||
*/
|
||||
//#define ENABLE_WIFI
|
||||
|
||||
/*
|
||||
* WiFi Settings
|
||||
* You can ignore these if you don't plan on using WiFi
|
||||
*/
|
||||
#ifdef ENABLE_WIFI
|
||||
#include <ESP8266WiFi.h>
|
||||
WiFiClient client;
|
||||
#define SPICEAPI_INTERFACE client
|
||||
#define SPICEAPI_INTERFACE_WIFICLIENT
|
||||
#define SPICEAPI_INTERFACE_WIFICLIENT_HOST "192.168.178.143"
|
||||
#define SPICEAPI_INTERFACE_WIFICLIENT_PORT 1337
|
||||
#define WIFI_SSID "MySSID"
|
||||
#define WIFI_PASS "MyWifiPassword"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the interface a serial connection will use.
|
||||
* You can change this to another Serial port, e.g. with an
|
||||
* Arduino Mega you can use Serial1/Serial2/Serial3.
|
||||
*/
|
||||
#ifndef ENABLE_WIFI
|
||||
#define SPICEAPI_INTERFACE Serial
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SpiceAPI Includes
|
||||
*
|
||||
* If you have the JSON strings beforehands or want to craft them
|
||||
* manually, you don't have to import the wrappers at all and can
|
||||
* use Connection::request to send and receive raw JSON strings.
|
||||
*/
|
||||
#include "connection.h"
|
||||
#include "wrappers.h"
|
||||
|
||||
/*
|
||||
* This global object represents the API connection.
|
||||
* The first parameter is the buffer size of the JSON string
|
||||
* we're receiving. So a size of 512 will only be able to
|
||||
* hold a JSON of 512 characters maximum.
|
||||
*
|
||||
* An empty password string means no password is being used.
|
||||
* This is the recommended when using Serial only.
|
||||
*/
|
||||
spiceapi::Connection CON(512, "changeme");
|
||||
|
||||
void setup() {
|
||||
|
||||
#ifdef ENABLE_WIFI
|
||||
|
||||
/*
|
||||
* When using WiFi, we can use the Serial interface for debugging.
|
||||
* You can open Serial Monitor and see what IP it gets assigned to.
|
||||
*/
|
||||
Serial.begin(57600);
|
||||
|
||||
// set WiFi mode to station (disables integrated AP)
|
||||
WiFi.mode(WIFI_STA);
|
||||
|
||||
// now try connecting to our Router/AP
|
||||
Serial.print("Connecting");
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
// print debug info over serial
|
||||
Serial.print("\nLocal IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Since the API makes use of the Serial module, we need to
|
||||
* set it up using our preferred baud rate manually.
|
||||
*/
|
||||
SPICEAPI_INTERFACE.begin(57600);
|
||||
while (!SPICEAPI_INTERFACE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
/*
|
||||
* Here's a few tests/examples on how to make use of the wrappers.
|
||||
*/
|
||||
|
||||
// insert cards for P1/P2
|
||||
spiceapi::card_insert(CON, 0, "E004012345678901");
|
||||
spiceapi::card_insert(CON, 1, "E004012345678902");
|
||||
|
||||
// insert a single coin / multiple coins
|
||||
spiceapi::coin_insert(CON);
|
||||
spiceapi::coin_insert(CON, 3);
|
||||
|
||||
// get the IIDX led ticker text
|
||||
char ticker[9];
|
||||
if (spiceapi::iidx_ticker_get(CON, ticker)) {
|
||||
// if a function returns true, that means success
|
||||
// now we can do something with the ticker as if it was a string
|
||||
//Serial1.println(ticker);
|
||||
}
|
||||
|
||||
// get AVS info
|
||||
spiceapi::InfoAvs avs_info {};
|
||||
if (spiceapi::info_avs(CON, avs_info)) {
|
||||
//Serial1.println(avs_info.model);
|
||||
}
|
||||
|
||||
// enter some keys on P1 keypad (blocks until sequence is entered fully)
|
||||
spiceapi::keypads_write(CON, 0, "1234");
|
||||
|
||||
// get light states
|
||||
spiceapi::LightState lights[8];
|
||||
size_t lights_size = spiceapi::lights_read(CON, lights, 8);
|
||||
for (size_t i = 0; i < lights_size; i++) {
|
||||
auto &light = lights[i];
|
||||
//Serial1.println(light.name);
|
||||
//Serial1.println(light.value);
|
||||
|
||||
// modify value to full bright
|
||||
light.value = 1.f;
|
||||
}
|
||||
|
||||
// send back modified light states
|
||||
spiceapi::lights_write(CON, lights, lights_size);
|
||||
|
||||
// refresh session (generates new crypt key, not that important for serial)
|
||||
spiceapi::control_session_refresh(CON);
|
||||
|
||||
// you can also manually send requests without the wrappers
|
||||
// this avoids json generation, but you still need to parse it in some way
|
||||
const char *answer_json = CON.request(
|
||||
"{"
|
||||
"\"id\": 0,"
|
||||
"\"module\":\"coin\","
|
||||
"\"function\":\"insert\","
|
||||
"\"params\":[]"
|
||||
"}"
|
||||
);
|
||||
|
||||
/*
|
||||
* For more functions/information, just check out wrappers.h yourself.
|
||||
* Have fun :)
|
||||
*/
|
||||
delay(5000);
|
||||
}
|
||||
716
api/resources/arduino/spiceapi/wrappers.h
Normal file
716
api/resources/arduino/spiceapi/wrappers.h
Normal file
@@ -0,0 +1,716 @@
|
||||
#ifndef SPICEAPI_WRAPPERS_H
|
||||
#define SPICEAPI_WRAPPERS_H
|
||||
|
||||
#define ARDUINOJSON_USE_LONG_LONG 1
|
||||
#include "ArduinoJson.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "connection.h"
|
||||
|
||||
// default buffer sizes
|
||||
#ifndef SPICEAPI_WRAPPER_BUFFER_SIZE
|
||||
#define SPICEAPI_WRAPPER_BUFFER_SIZE 256
|
||||
#endif
|
||||
#ifndef SPICEAPI_WRAPPER_BUFFER_SIZE_STR
|
||||
#define SPICEAPI_WRAPPER_BUFFER_SIZE_STR 256
|
||||
#endif
|
||||
|
||||
namespace spiceapi {
|
||||
|
||||
/*
|
||||
* Structs
|
||||
*/
|
||||
|
||||
struct AnalogState {
|
||||
String name = "";
|
||||
float value = 0.f;
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
struct ButtonState {
|
||||
String name = "";
|
||||
float value = 0.f;
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
struct LightState {
|
||||
String name = "";
|
||||
float value = 0.f;
|
||||
bool enabled = false;
|
||||
};
|
||||
|
||||
struct InfoAvs {
|
||||
String model, dest, spec, rev, ext;
|
||||
};
|
||||
|
||||
struct InfoLauncher {
|
||||
String version;
|
||||
String compile_date, compile_time, system_time;
|
||||
String args;
|
||||
};
|
||||
|
||||
struct InfoMemory {
|
||||
uint64_t mem_total, mem_total_used, mem_used;
|
||||
uint64_t vmem_total, vmem_total_used, vmem_used;
|
||||
};
|
||||
|
||||
struct TouchState {
|
||||
uint64_t id;
|
||||
int64_t x, y;
|
||||
};
|
||||
|
||||
// static storage
|
||||
char JSON_BUFFER_STR[SPICEAPI_WRAPPER_BUFFER_SIZE_STR];
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
uint64_t msg_gen_id() {
|
||||
static uint64_t id_global = 0;
|
||||
return ++id_global;
|
||||
}
|
||||
|
||||
char *doc2str(DynamicJsonDocument *doc) {
|
||||
char *buf = JSON_BUFFER_STR;
|
||||
serializeJson(*doc, buf, SPICEAPI_WRAPPER_BUFFER_SIZE_STR);
|
||||
return buf;
|
||||
}
|
||||
|
||||
DynamicJsonDocument *request_gen(const char *module, const char *function) {
|
||||
|
||||
// create document
|
||||
auto doc = new DynamicJsonDocument(SPICEAPI_WRAPPER_BUFFER_SIZE);
|
||||
|
||||
// add attributes
|
||||
(*doc)["id"] = msg_gen_id();
|
||||
(*doc)["module"] = module;
|
||||
(*doc)["function"] = function;
|
||||
|
||||
// add params
|
||||
(*doc).createNestedArray("params");
|
||||
|
||||
// return document
|
||||
return doc;
|
||||
}
|
||||
|
||||
DynamicJsonDocument *response_get(Connection &con, const char *json) {
|
||||
|
||||
// parse document
|
||||
DynamicJsonDocument *doc = new DynamicJsonDocument(SPICEAPI_WRAPPER_BUFFER_SIZE);
|
||||
auto err = deserializeJson(*doc, (char *) json);
|
||||
|
||||
// check for parse error
|
||||
if (err) {
|
||||
|
||||
// reset cipher
|
||||
con.cipher_alloc();
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check id
|
||||
if (!(*doc)["id"].is<int64_t>()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check errors
|
||||
auto errors = (*doc)["errors"];
|
||||
if (!errors.is<JsonArray>()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check error count
|
||||
if (errors.as<JsonArray>().size() > 0) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check data
|
||||
if (!(*doc)["data"].is<JsonArray>()) {
|
||||
delete doc;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return document
|
||||
return doc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrappers
|
||||
*/
|
||||
|
||||
size_t analogs_read(Connection &con, AnalogState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("analogs", "read");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
auto data = (*res)["data"].as<JsonArray>();
|
||||
size_t buffer_count = 0;
|
||||
for (auto val : data) {
|
||||
if (buffer_count >= buffer_elements) {
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
buffer[buffer_count].name = (const char*) val[0];
|
||||
buffer[buffer_count].value = val[1];
|
||||
buffer[buffer_count].enabled = val[2];
|
||||
buffer_count++;
|
||||
}
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
|
||||
bool analogs_write(Connection &con, AnalogState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("analogs", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
data.add(state.value);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool analogs_write_reset(Connection &con, AnalogState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("analogs", "write_reset");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t buttons_read(Connection &con, ButtonState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("buttons", "read");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
auto data = (*res)["data"].as<JsonArray>();
|
||||
size_t buffer_count = 0;
|
||||
for (auto val : data) {
|
||||
if (buffer_count >= buffer_elements) {
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
buffer[buffer_count].name = (const char*) val[0];
|
||||
buffer[buffer_count].value = val[1];
|
||||
buffer[buffer_count].enabled = val[2];
|
||||
buffer_count++;
|
||||
}
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
|
||||
bool buttons_write(Connection &con, ButtonState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("buttons", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
data.add(state.value);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool buttons_write_reset(Connection &con, ButtonState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("buttons", "write_reset");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool card_insert(Connection &con, size_t index, const char *card_id) {
|
||||
auto req = request_gen("card", "insert");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(index);
|
||||
params.add(card_id);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool coin_get(Connection &con, int &coins) {
|
||||
auto req = request_gen("coin", "insert");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
coins = (*res)["data"][0];
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool coin_set(Connection &con, int coins) {
|
||||
auto req = request_gen("coin", "set");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(coins);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool coin_insert(Connection &con, int coins=1) {
|
||||
auto req = request_gen("coin", "insert");
|
||||
if (coins != 1) {
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(coins);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_raise(Connection &con, const char *signal) {
|
||||
auto req = request_gen("control", "raise");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(signal);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_exit(Connection &con) {
|
||||
auto req = request_gen("control", "exit");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_exit(Connection &con, int exit_code) {
|
||||
auto req = request_gen("control", "exit");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(exit_code);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_restart(Connection &con) {
|
||||
auto req = request_gen("control", "restart");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_session_refresh(Connection &con) {
|
||||
auto req = request_gen("control", "session_refresh");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
const char *key = (*res)["data"][0];
|
||||
con.change_pass(key, true);
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_shutdown(Connection &con) {
|
||||
auto req = request_gen("control", "shutdown");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool control_reboot(Connection &con) {
|
||||
auto req = request_gen("control", "reboot");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iidx_ticker_get(Connection &con, char *ticker) {
|
||||
auto req = request_gen("iidx", "ticker_get");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
const char *data = (*res)["data"][0];
|
||||
strncpy(ticker, data, 9);
|
||||
ticker[9] = 0x00;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iidx_ticker_set(Connection &con, const char *ticker) {
|
||||
auto req = request_gen("iidx", "ticker_set");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(ticker);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool iidx_ticker_reset(Connection &con) {
|
||||
auto req = request_gen("iidx", "ticker_reset");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool info_avs(Connection &con, InfoAvs &info) {
|
||||
auto req = request_gen("info", "avs");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
auto data = (*res)["data"][0];
|
||||
info.model = (const char*) data["model"];
|
||||
info.dest = (const char*) data["dest"];
|
||||
info.spec = (const char*) data["spec"];
|
||||
info.rev = (const char*) data["rev"];
|
||||
info.ext = (const char*) data["ext"];
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool info_launcher(Connection &con, InfoLauncher &info) {
|
||||
auto req = request_gen("info", "launcher");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
auto data = (*res)["data"][0];
|
||||
info.version = (const char*) data["version"];
|
||||
info.compile_date = (const char*) data["compile_date"];
|
||||
info.compile_time = (const char*) data["compile_time"];
|
||||
info.system_time = (const char*) data["system_time"];
|
||||
for (auto arg : data["args"].as<JsonArray>()) {
|
||||
info.args += (const char*) arg;
|
||||
info.args += " ";
|
||||
// TODO: remove last space
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool info_memory(Connection &con, InfoMemory &info) {
|
||||
auto req = request_gen("info", "memory");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
auto data = (*res)["data"][0];
|
||||
info.mem_total = data["mem_total"];
|
||||
info.mem_total_used = data["mem_total_used"];
|
||||
info.mem_used = data["mem_used"];
|
||||
info.vmem_total = data["vmem_total"];
|
||||
info.vmem_total_used = data["vmem_total_used"];
|
||||
info.vmem_used = data["vmem_used"];
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool keypads_write(Connection &con, unsigned int keypad, const char *input) {
|
||||
auto req = request_gen("keypads", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(keypad);
|
||||
params.add(input);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str, 1000 + strlen(input) * 300));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool keypads_set(Connection &con, unsigned int keypad, const char *keys) {
|
||||
auto keys_len = strlen(keys);
|
||||
auto req = request_gen("keypads", "set");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(keypad);
|
||||
for (size_t i = 0; i < keys_len; i++) {
|
||||
char buf[] = {keys[i], 0x00};
|
||||
params.add(buf);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool keypads_get(Connection &con, unsigned int keypad, char *keys, size_t keys_len) {
|
||||
auto req = request_gen("keypads", "get");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(keypad);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
for (auto key : (*res)["data"].as<JsonArray>()) {
|
||||
const char *key_str = key;
|
||||
if (key_str != nullptr && keys_len > 0) {
|
||||
*(keys++) = key_str[0];
|
||||
keys_len--;
|
||||
}
|
||||
}
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t lights_read(Connection &con, LightState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("lights", "read");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
auto data = (*res)["data"].as<JsonArray>();
|
||||
size_t buffer_count = 0;
|
||||
for (auto val : data) {
|
||||
if (buffer_count >= buffer_elements) {
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
buffer[buffer_count].name = (const char*) val[0];
|
||||
buffer[buffer_count].value = val[1];
|
||||
buffer[buffer_count].enabled = val[2];
|
||||
buffer_count++;
|
||||
}
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
|
||||
bool lights_write(Connection &con, LightState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("lights", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
data.add(state.value);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lights_write_reset(Connection &con, LightState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("lights", "write_reset");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.name);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_write(Connection &con, const char *dll_name, const char *hex, uint32_t offset) {
|
||||
auto req = request_gen("memory", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(dll_name);
|
||||
params.add(hex);
|
||||
params.add(offset);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_read(Connection &con, const char *dll_name, uint32_t offset, uint32_t size, String &hex) {
|
||||
auto req = request_gen("memory", "read");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(dll_name);
|
||||
params.add(offset);
|
||||
params.add(size);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
hex = (const char*) (*res)["data"][0];
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool memory_signature(Connection &con, const char *dll_name, const char *signature,
|
||||
const char *replacement, uint32_t offset, uint32_t usage, uint32_t &file_offset) {
|
||||
auto req = request_gen("memory", "signature");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
params.add(dll_name);
|
||||
params.add(signature);
|
||||
params.add(replacement);
|
||||
params.add(offset);
|
||||
params.add(usage);
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
file_offset = (*res)["data"][0];
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t touch_read(Connection &con, TouchState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("touch", "read");
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return 0;
|
||||
|
||||
auto data = (*res)["data"].as<JsonArray>();
|
||||
size_t buffer_count = 0;
|
||||
for (auto val : data) {
|
||||
if (buffer_count >= buffer_elements) {
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
buffer[buffer_count].id = val[0];
|
||||
buffer[buffer_count].x = val[1];
|
||||
buffer[buffer_count].y = val[2];
|
||||
buffer_count++;
|
||||
}
|
||||
delete res;
|
||||
return buffer_count;
|
||||
}
|
||||
|
||||
bool touch_write(Connection &con, TouchState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("touch", "write");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.id);
|
||||
data.add(state.x);
|
||||
data.add(state.y);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool touch_write_reset(Connection &con, TouchState *buffer, size_t buffer_elements) {
|
||||
auto req = request_gen("touch", "write_reset");
|
||||
auto params = (*req)["params"].as<JsonArray>();
|
||||
for (size_t i = 0; i < buffer_elements; i++) {
|
||||
auto &state = buffer[i];
|
||||
auto data = params.createNestedArray();
|
||||
data.add(state.id);
|
||||
}
|
||||
auto req_str = doc2str(req);
|
||||
delete req;
|
||||
auto res = response_get(con, con.request(req_str));
|
||||
if (!res)
|
||||
return false;
|
||||
delete res;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif //SPICEAPI_WRAPPERS_H
|
||||
Reference in New Issue
Block a user