Skip to content

Commit

Permalink
add /templates endpoint and include types+templates+conditions+chains…
Browse files Browse the repository at this point in the history
… in dump output
  • Loading branch information
john30 committed Oct 22, 2023
1 parent b752062 commit b901232
Show file tree
Hide file tree
Showing 9 changed files with 311 additions and 22 deletions.
129 changes: 119 additions & 10 deletions contrib/html/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ openapi: 3.1.0
info:
title: ebusd-http
description: The API that ebusd provides on HTTP port.
version: "23.2"
version: "23.3"
servers:
- url: http://127.0.0.1:8080/
paths:
Expand Down Expand Up @@ -145,6 +145,50 @@ paths:
500:
description: General error.
content: { }
/templates:
get:
summary: Get all known field templates for the root.
responses:
200:
description: Success.
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/Templates'
400:
description: Invalid request parameters.
content: { }
403:
description: User not authorized.
content: { }
500:
description: General error.
content: { }
/templates/{path}:
get:
summary: Get all known field templates for the path.
parameters:
- name: path
in: path
required: true
schema:
type: string
responses:
200:
description: Success.
content:
application/json;charset=utf-8:
schema:
$ref: '#/components/schemas/Templates'
400:
description: Invalid request parameters.
content: { }
403:
description: User not authorized.
content: { }
500:
description: General error.
content: { }
/raw:
get:
summary: Retrieve raw data from grabbed and/or decoded messages.
Expand Down Expand Up @@ -392,8 +436,12 @@ components:
type: integer
minimum: 0
condition:
type: string
description: the condition string in case of a conditional message (only with full).
description: the condition(s) in case of a conditional message (only with full).
oneOf:
- $ref: '#/components/schemas/Condition'
- type: array
items:
$ref: '#/components/schemas/Condition'
lastup:
$ref: '#/components/schemas/Seconds'
description: the time in UTC seconds of the last update of the message (0
Expand All @@ -407,8 +455,12 @@ components:
description: destination master or slave address.
example: 8
id:
$ref: '#/components/schemas/Symbols'
description: the message ID composed of PBSB and further master data bytes (only with def).
description: the message ID composed of PBSB and further master data bytes (only with def), or an array thereof in case of a chained message.
oneOf:
- $ref: '#/components/schemas/Symbols'
- type: array
items:
$ref: '#/components/schemas/Symbols'
comment:
type: string
description: the message comment (only with verbose).
Expand Down Expand Up @@ -465,10 +517,10 @@ components:
- type: string
- type: number
nullable: true
FieldDef:
FieldTemplate:
description: a single field template.
required:
- name
- slave
- type
- isbits
- length
Expand All @@ -477,9 +529,6 @@ components:
name:
type: string
description: the field name.
slave:
type: boolean
description: whether the field is part of the slave data.
type:
type: string
description: the field type.
Expand Down Expand Up @@ -513,6 +562,66 @@ components:
comment:
type: string
description: the field comment.
FieldDef:
description: a single field definition.
allOf:
- $ref: '#/components/schemas/FieldTemplate'
- type: object
required:
- slave
properties:
slave:
type: boolean
description: whether the field is part of the slave data.
Templates:
type: array
description: list of known field templates.
items:
oneOf:
- $ref: '#/components/schemas/FieldTemplate'
- type: object
required:
- name
- sequence
properties:
name:
type: string
description: the template set name.
sequence:
type: array
description: the sequence of fields.
items:
$ref: '#/components/schemas/FieldTemplate'
Condition:
description: a single condition.
required:
- name
- message
properties:
name:
type: string
description: name of the condition.
message:
type: string
description: name of the referenced message.
circuit:
type: string
description: name of the referenced circuit.
zz:
maximum: 255
minimum: 0
type: integer
description: the circuit slave address.
field:
type: string
description: the field name in the referenced message.
value:
type: array
description: the value ranges for the condition.
items:
oneOf:
- type: number
- type: string
DataType:
description: a known field data type.
type: object
Expand Down
7 changes: 7 additions & 0 deletions src/ebusd/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,14 @@ int main(int argc, char* argv[], char* envp[]) {
} else {
logNotice(lf_main, "configuration dump:");
}
*out << "{\"datatypes\":[";
DataTypeList::getInstance()->dump(s_opt.dumpConfig, true, out);
*out << "],\"templates\":[";
const auto tmpl = s_scanHelper->getTemplates("");
tmpl->dump(s_opt.dumpConfig, out);
*out << "],\"messages\":";
s_messageMap->dump(true, s_opt.dumpConfig, out);
*out << "}";
if (fout.is_open()) {
fout.close();
}
Expand Down
12 changes: 12 additions & 0 deletions src/ebusd/mainloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2254,6 +2254,18 @@ result_t MainLoop::executeGet(const vector<string>& args, bool* connected, ostri
return formatHttpResult(ret, type, ostream);
}

if (uri == "/templates" || uri.substr(0, 11) == "/templates/") {
*ostream << "[";
OutputFormat verbosity = OF_NAMES|OF_JSON|OF_ALL_ATTRS;
string name = uri == "/templates" ? "" : uri.substr(11) + "/";
const auto tmpl = m_scanHelper->getTemplates(name);
tmpl->dump(verbosity, ostream);
*ostream << "\n]";
type = 6;
*connected = false;
return formatHttpResult(ret, type, ostream);
}

if (uri == "/raw") {
time_t since = 0, until = 0;
bool onlyUnknown = false;
Expand Down
13 changes: 13 additions & 0 deletions src/ebusd/scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,19 @@ bool ScanHelper::readTemplates(const string relPath, const string extension, boo
return false;
}

void ScanHelper::dumpTemplates(OutputFormat outputFormat, ostream* output) const {
bool prependSeparator = false;
for (auto it : m_templatesByPath) {
if (prependSeparator) {
*output << ",";
}
const auto templates = it.second;
if (templates->dump(outputFormat, output)) {
prependSeparator = true;
}
}
}

result_t ScanHelper::readConfigFiles(const string& relPath, const string& extension, bool recursive,
string* errorDescription) {
vector<string> files, dirs;
Expand Down
7 changes: 7 additions & 0 deletions src/ebusd/scan.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ class ScanHelper : public Resolver {
*/
bool readTemplates(const string relPath, const string extension, bool available);

/**
* Dump the loaded @a DataFieldTemplates to the output.
* @param outputFormat the @a OutputFormat options.
* @param output the @a ostream to dump to.
*/
void dumpTemplates(OutputFormat outputFormat, ostream* output) const;

/**
* Read the configuration files from the specified path.
* @param relPath the relative path from which to read the files (without trailing "/").
Expand Down
28 changes: 27 additions & 1 deletion src/lib/ebus/data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,10 @@ void SingleDataField::dumpPrefix(bool prependFieldSeparator, OutputFormat output
dumpString(prependFieldSeparator, m_name, output);
}
if (outputFormat & OF_JSON) {
*output << ", \"slave\": " << (m_partType == pt_slaveData ? "true" : "false") << ", ";
if (m_partType != pt_any) {
*output << ", \"slave\": " << (m_partType == pt_slaveData ? "true" : "false");
}
*output << ", ";
} else {
*output << FIELD_SEPARATOR;
if (m_partType == pt_masterData) {
Expand Down Expand Up @@ -1459,4 +1462,27 @@ const DataField* DataFieldTemplates::get(const string& name) const {
return ref->second;
}

bool DataFieldTemplates::dump(OutputFormat outputFormat, ostream* output) const {
bool prependFieldSeparator = false;
for (const auto &it : m_fieldsByName) {
const DataField *dataField = it.second;
if (outputFormat & OF_JSON) {
if (dataField->isSet()) {
if (prependFieldSeparator) {
*output << ",\n";
}
*output << "{\"name\":\"" << dataField->getName(-1) << "\", \"sequence\": [";
dataField->dump(false, outputFormat, output);
*output << "]}";
} else {
dataField->dump(prependFieldSeparator, outputFormat, output);
}
} else {
dataField->dump(prependFieldSeparator, outputFormat, output);
}
prependFieldSeparator = true;
}
return !prependFieldSeparator;
}

} // namespace ebusd
8 changes: 8 additions & 0 deletions src/lib/ebus/data.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,14 @@ class DataFieldTemplates : public MappedFileReader {
*/
const DataField* get(const string& name) const;

/**
* Dump the templates to the output.
* @param outputFormat the @a OutputFormat options.
* @param output the @a ostream to dump to.
* @return true when a template was written to the output.
*/
bool dump(OutputFormat outputFormat, ostream* output) const;


private:
/** the known template @a DataField instances by name. */
Expand Down
Loading

0 comments on commit b901232

Please sign in to comment.