This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
Module RESTful API
RESTful-API documentation including usage examples
The API allows you to use the function of each module.
The basic components like URL structure, versioning and error handling are generic over all modules.
Guide for rapid implementation
This guide is intended to enable a quick implementation and explain the most important points.
- Implement the version check and device selection.
This point is very important because we don’t want problematic implementations that go crazy after an update!
- Implement proper error handling.
- After the version check and device selection reset the device to initial state using /reset.
This is not needed if the application uses only “read” requests.
- Start by implementing all the GET requests and proceed with POST requests later.
- Some functions like /hard_reset, /watchdog or /limits can reset the entire system.
We do not recommend to implement them if they are not needed by the application!
- Implement the /notification endpoint if it is required by the documentation.
Important notes
- Requests & Responses are JSON only.
- The JSON structure is case sensitive.
- The API does not support multiple “writable” applications at the same time.
The driver takes care of it, but the applications will eventually lose track of the state.
- Multiple parallel requests will increase the individual request time as they are not cached.
- Authentication is handled by a proxy server.
Multicast DNS auto detection
The API can be detected using mDNS queries.
The service type are “_https._tcp” and “_https._tcp”.
The configuration may be extended by additional txt records in the future. You can find the latest config under /etc/avahi/services/nexus-rest-*.service
The mDNS config (avahi) looks like this:
<service-group>
<name replace-wildcards="yes">NOREYA NEXUS IO Module API (%h)</name>
<service>
<type>_http._tcp</type>
<port>80</port>
<txt-record>vendor=noreyatech</txt-record>
<txt-record>path=/api/io/</txt-record>
<txt-record>service=io-module</txt-record>
<txt-record>machine-id=/nexus-machine-id</txt-record>
<txt-record>tls-ca=/noreya-nexus/certificates/ca.pem</txt-record>
</service>
<service>
<type>_https._tcp</type>
<port>443</port>
<txt-record>vendor=noreyatech</txt-record>
<txt-record>path=/api/io/</txt-record>
<txt-record>service=io-module</txt-record>
<txt-record>machine-id=/nexus-machine-id</txt-record>
<txt-record>tls-ca=/noreya-nexus/certificates/ca.pem</txt-record>
</service>
</service-group>
Secure communication via HTTPS
It is recommended to secure and trust the communication via HTTPS.
You can retrieve the certificate of the X.509/PEM certification authority via the path in the TXT entry “tls-ca”.
The TLS certificate is valid for the propagated host name and all other host names or IP addresses configured under :
http://noreya-nexus.local/nexuscontrolui/system/settings#tls-cert
You should import this certificate on the client and use it for further communication (“trust on first connection strategy”).
Machine ID check
The mDNS implementation handles devices with the same hostname (noreya-nexus) by appending a number (noreya-nexus.local, noreya-nexus-2.local…).
This is great, but has one big problem: If you have 3 hosts and the second one goes offline, the third one gets the second number (noreya-nexus-2.local).
To avoid problems with this behavior, you need to check the unique machine-id provided by the path (plain/txt) in the TXT entry “machine-id”.
We recommend using static IPs or router-defined hostnames (.lan) to avoid this problem, but implementations must deal with this.
1 - Version check and device selection
Describes the /version, /reset and /descriptor endpoints.
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
Tokens can be generated on the http://noreya-nexus.local/nexuscontrolui/system/settings#access-token page.
The username is always “token” while the password must be token value.
You may also want to use the secure protocol https://.
GET /
The “/” (/1.0,/1.1,…) endpoint shows version information and all connected devices handled by this driver.
The “version": “api”: {…} resource must be checked for compatibility by any client.
The “devices” array contains all usable devices and the “slot_number” number must be used to build the further URL.
e.g: “slot_number” is 3:
<HOSTNAME>/api/<service>/<version>/3/descriptor
For the versioning strategy and format, see the Versioning chapter.
The fields “driver_session” and “device_session” must stored by the client and checked frequently.
If any of the values change the client must re-initialize the device.
Request:
Method: GET
URL : localhost/api/<service>/<version>/
Response:
{
"driver_session": "<String>",
"version": {
"api": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"service": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"module_driver": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"kernel_driver": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
}
},
"devices": [
{
"slot_number": <uint>,
"sdbp_version": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"device_session": "<String>"
}
]
}
Example:
Request:
curl http://localhost/api/bmc/1.0/
Response:
{
"driver_session": "ZVHGTLCFDUD1FKLJCHG5PWYULHVRJ8AV7Q8A2W703UHVYZFYJPWUCYNDSR65AWUU",
"version": {
"api": {
"major": 0,
"minor": 9,
"patch": 0
},
"service": {
"major": 0,
"minor": 9,
"patch": 0
},
"module_driver": {
"major": 0,
"minor": 9,
"patch": 0
},
"kernel_driver": {
"major": 1,
"minor": 1,
"patch": 0
}
},
"devices": [
{
"slot_number": 0,
"sdbp_version": {
"major": 1,
"minor": 0,
"patch": 0
},
"device_session": "AAHGTLCFDUD1FKLJCHG5PWYULHVRJ8AV7Q8A2W703UHVYZFYJPWUCYNDSR65AWSS"
}
]
}
POST /reset
Resets the entire module to the initial state.
This is equal to a driver restart (SUSPEND) not a system reset (SYSTEM_RESET).
Request:
Method: POST
URL: localhost/api/<service>/<version>/<slot>/reset
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/reset --header "Content-Type: application/json" --request POST --data '{"reset": "yes"}'
Response:
GET /descriptor
The “/descriptor” endpoint shows the device descriptor.
Request:
Method: GET
URL : localhost/api/<service>/<version>/<slot>/descriptor
Response:
{
"slot_number": <uint>,
"vendor_product_id": <string>,
"product_name": <string>,
"vendor_name": <string>,
"serial_code": <string>,
"fw_version": {
"stability": <string>,
"version": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
}
},
"hw_version": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"protocol_version": {
"major": <uint>,
"minor": <uint>,
"patch": <uint>
},
"bootloader_state": <string>,
"max_frame_size": <uint>,
"max_power_12v": <uint>,
"max_power_5v0": <uint>,
"max_power_3v3": <uint>,
"max_sclk_speed": <uint>
}
Example:
Request:
curl http://localhost/api/bmc/1.0/0/descriptor
Response:
{
"slot_number": 0,
"vendor_product_id": "modules.noreya.tech/bmc",
"product_name": "Baseboard Management Controller",
"vendor_name": "NOREYA",
"serial_code": "0000-0000-2039-3639-424E-5317-003A-0036",
"fw_version": {
"stability": "A",
"version": {
"major": 0,
"minor": 9,
"patch": 3
}
},
"hw_version": {
"major": 4,
"minor": 1,
"patch": 1
},
"protocol_version": {
"major": 1,
"minor": 0,
"patch": 0
},
"bootloader_state": "supported",
"max_frame_size": 64,
"max_power_12v": 0,
"max_power_5v0": 550,
"max_power_3v3": 7915,
"max_sclk_speed": 16000
}
2 - Error response handling
Describes how errors should be handled.
On error the HTTP status code is set in the response.
At least the following status codes should be handled: 400, 404, 422, 500, 502 .
The http status code MUST be checked by any application!
It is not valid to process only the response body because proxy servers may modify it.
Note: The http status code is not equal to the “code” field in the body!
All endpoints use a generic response format.
status is always “error”
code is an integer value equal to the http status code
message is a string with a meaningful error message
Error messages are only for human interpretation.
It is not recommended to parse for specific error messages!
Response:
{
"status": "error",
"code": <http error code(integer)>,
"message": <String>
}
Example (Not Found)
Request:
curl http://localhost/api/bmc/1.0/0/error_msg
Response:
{
"status": "error",
"code": 404,
"message": "Not Found"
}
Example (Unprocessable Entity)
Request:
curl http://localhost/api/bmc/1.0/0/buzzer --header "Content-Type: application/json" --request POST --data '{"mode": 4, "duration": 0}'
Response:
{
"status": "error",
"code": 422,
"message": "duration out of range"
}
3 - IO Module
IO Module RESTful API documentation
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Introduction
The IO Module provides six IOs configureable via RESTful API.
From the implementation perspective the following order should be used:
- Implement version check and device selection
- Implement GET /input/values for testing
- Implement notification error handling and polling
- Implement power management
- Implement outputs
- Test if power management, outputs and notifications (e.g: shortcut a pin) is working
- Implement all remaining endpoints
Base URL:
<HOSTNAME>/api/io/<version>/
Version check and device selection
See Version check and device selection
Error response
See Error Response
Caching
By default, all values in the /input directory are cached for 1 second to improve performance during parallel access. To override this cache mechanism, simply add the header cache-control: no-cache
to your request.
Notification
GET /notification
Returns pending notifications.
Notifications are messages initiated and send by the module on configured events or (external) errors.
They are handled fast and are usually available >20ms after the event occurred (from the RESTful API point of view).
The /notification endpoint MUST be queried periodically during operation by the application to detect external errors!
To prevent damage to the hardware all events except custom_voltage_alert will disable the affected pin.
The pin falls back to analog input mode because the device is designed to handle the entire maximum voltage without damage.
Request:
Method: GET
URL: <HOSTNAME>/api/io/<version>/<slot>/notification/<pin>
Parameters:
Response:
{
"under_voltage_alert": <bool>,
"high_voltage_alert": <bool>,
"high_current_alert": <bool>,
"custom_voltage_alert": <bool>
}
Example
Request:
curl http://localhost/api/io/1.0/3/notification/1
Response:
{
"under_voltage_alert": false,
"high_voltage_alert": false,
"high_current_alert": false,
"custom_voltage_alert": true
}
Power Management
POST /power-management
Too handle different power supply capacities the NOREYA NEXUS platform uses a passive power management concept.
This means that each module must specify its maximum power consumption and the total sum of the maximum power must not exceed the power supply capacity.
The power management daemon can be configured to handle this limit “strict” (do not allow overprovisioning) or “weak” (allow overprovisioning and warn).
The IO Module supports dynamic power configuration which means the application (and therefore the user) must specify how much maximum power per pin is used.
Before the /output/ commands can be used a valid power management configuration must be set.
The position in the array is analog to the pin number.
Please check the current limit for the 5V/12V rail from the datasheet/webpage!
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/power-management
Parameters:
{
"config": [
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
},
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
},
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
},
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
},
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
},
{
"rail": "5_volt|12_volt",
"current_milliampere": <int>
}
]
}
Response:
{
"status": "success|denied",
"too_much_power": {
"rail_3v3_milliwatt": <int>,
"rail_5v0_milliwatt": <int>,
"rail_12v_milliwatt": <int>
}
}
Example
Request:
curl http://localhost/api/io/1.0/3/power-management --header "Content-Type: application/json" --request POST --data '{"config": [{"rail": "5_volt", "current_milliampere": 1}, {"rail": "5_volt", "current_milliampere": 1}, {"rail": "5_volt", "current_milliampere": 1}, {"rail": "5_volt", "current_milliampere": 1}, {"rail": "5_volt", "current_milliampere": 1}, {"rail": "5_volt", "current_milliampere": 1}]}'
Response:
{
"status": "success",
"too_much_power": {
"rail_3v3_milliwatt": 0,
"rail_5v0_milliwatt": 0,
"rail_12v_milliwatt": 0
}
}
Returns the value and type for each pin.
If the pin is configured as analog input, output or pwm the type is “voltage_millivolt” and the value is returned in millivolt.
In output mode the value represents the current voltage level at the pin. The value is load and frequency dependent.
As digital input the type is “digital_input” and the value represents the current logical state 0 (LOW) or 1 (HIGH).
As frequency counter the type is “frequency_hertz” and the value represents the current frequency in Hertz.
Please consider the minimum and maximum frequency value from the datasheet/webpage!
Request:
Method: GET
URL: <HOSTNAME>/api/io/<version>/<slot>/input/values
Parameters:
Response:
{
"pins": [
{
"pin": 1,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
},
{
"pin": 2,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
},
{
"pin": 3,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
},
{
"pin": 4,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
},
{
"pin": 5,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
},
{
"pin": 6,
"pin_type": "voltage_millivolt | digital_input | frequency_hertz",
"value": <int>
}
]
}
Example
Request:
curl http://localhost/api/io/1.0/3/input/values
Response:
{
"pins": [
{
"pin": 1,
"pin_type": "voltage_millivolt",
"value": 3300
},
{
"pin": 2,
"pin_type": "digital_input",
"value": 1
},
{
"pin": 3,
"pin_type": "voltage_millivolt",
"value": 0
},
{
"pin": 4,
"pin_type": "frequency_hertz",
"value": 2000
},
{
"pin": 5,
"pin_type": "voltage_millivolt",
"value": 0
},
{
"pin": 6,
"pin_type": "voltage_millivolt",
"value": 0
}
]
}
Returns the current value for each pin.
The electrical current value is in milliampere.
It is returned independent from the configured mode but is usually zero in input modes.
Please note that this value includes the switching transistor loss.
This means the value will be not accurate especially in pwm mode!
The precision can be compensated by a calibration.
Request:
Method: GET
URL: <HOSTNAME>/api/io/<version>/<slot>/input/values/current
Parameters:
Response:
{
"pins": [
{
"pin": 1,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 2,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 3,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 4,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 5,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 6,
"pin_type": "current_milliampere",
"value": 0
}
]
}
Example
Request:
curl http://localhost/api/io/1.0/3/input/values/current
Response:
{
"pins": [
{
"pin": 1,
"pin_type": "current_milliampere",
"value": 212
},
{
"pin": 2,
"pin_type": "current_milliampere",
"value": 42
},
{
"pin": 3,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 4,
"pin_type": "current_milliampere",
"value": 0
},
{
"pin": 5,
"pin_type": "current_milliampere",
"value": 345
},
{
"pin": 6,
"pin_type": "current_milliampere",
"value": 0
}
]
}
POST /input/mode
Changes the input mode of a pin to analog or digital.
After RESET/SUSPEND the pin is always in analog mode.
Setting a pin to analog mode resets the config, including the analog threshold.
Please check /input/values for the values.
The analog mode is implicitly enabled when the pin is in output/pwm mode, /input/values and /input/analog/thresholds are available.
The digital mode can not be combined with analog/output/pwm modes.
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/input/mode
Parameters:
{
"pin": <int>,
"mode": "analog|digital"
}
Response:
Example
Request:
curl http://localhost/api/io/1.0/3/input/mode --header "Content-Type: application/json" --request POST --data '{"pin": 1, "mode": "analog"}'
Response:
POST /input/analog/threshold
Enables or disables the analog threshold mode.
The pin must be set into analog mode before the threshold can be enabled.
In analog threshold mode each threshold event triggers a notification on the SDBP.
The result must be checked via /notification endpoint.
The threshold_millivolt can be any value between the 50mV and 25000mV.
Please note that in the current implementation only the state “interrupt triggered” is stored, but not how often.
The api does currently not offer a “debounce_time_milliseconds” parameter. We recommend polling /input/values if this necessary.
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/input/analog/threshold
Parameters:
{
"pin": <int>,
"threshold_millivolt": <int>,
"trigger": "disabled|rising|falling"
}
Response:
Example
Request:
curl http://localhost/api/io/1.0/3/input/analog/threshold --header "Content-Type: application/json" --request POST --data '{"pin": 1, "threshold_millivolt": 2000, "trigger": "rising"}'
Response:
POST /input/digital/interrupt
Enables or disables the digital interrupt mode.
The pin must be set into digital mode before the interrupt can be enabled.
In digital interrupt mode each interrupt triggers a notification on the SDBP.
The result must be checked via /notification endpoint.
Please note that in the current implementation only the state “interrupt triggered” is stored, but not how often.
The debounce_time_milliseconds is a value between 0 and 1000 milliseconds.
After the first trigger event the firmware waits debounce_time_milliseconds before sending a notification for a new event.
All events in this period are ignored.
This setting is used to prevent interrupt notifications spamming the bus.
It is recommended to set the debounce_time_milliseconds to 20ms or higher.
Some things like switches or buttons typically require a ~250ms debounce_time_milliseconds to send one event per switch/press.
Please check the datasheet/webpage of the module for the HIGH/LOW thresholds.
In case you have different requirements we recommend to use the /input/analog/threshold endpoint.
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/input/digital/interrupt
Parameters:
{
"pin": <int>,
"debounce_time_milliseconds": <int>,
"trigger": "disabled|rising|falling|pulse"
}
Response:
Example
Request:
curl http://localhost/api/io/1.0/3/input/digital/interrupt --header "Content-Type: application/json" --request POST --data '{"pin": 1, "debounce_time_milliseconds": 100, "trigger": "rising"}'
Response:
POST /input/digital/counter
Enables or disables the digital counter mode.
The pin must be set into digital mode before the counter can be enabled.
Check /input/values for the counter values.
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/input/digital/counter
Parameters:
{
"pin": <int>,
"state": "enabled|disabled"
}
Response:
Example
Request:
curl http://localhost/api/io/1.0/3/input/digital/counter --header "Content-Type: application/json" --request POST --data '{"pin": 1, "state": "enabled"}'
Response:
Output
POST /output/state
Configures the output state.
The pin is automatically reset and configured as output if the previous mode was different.
A valid power configuration must exist before this command can be used.
Check /input/values for the values.
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/output/state
Parameters:
{
"pin": <int>,
"state": "high|low"
}
Response:
Example
Request:
curl http://localhost/api/io/1.0/3/output/state --header "Content-Type: application/json" --request POST --data '{"pin": 1, "state": "high"}'
Response:
POST /output/pwm
Configures the output as pwm output.
The pin is automatically reset and configured as output if the previous mode was different.
A valid power configuration must exist before this command can be used.
Check /input/values for the values.
The pwm function is based on a 16-bit timer with a base frequency of 48MHz.
To configure the PWM the following parameters are important:
prescaler: Divisor for the 48MHz clock.
period: Amount of ticks to reach the target frequency.
time_on: Amount of ticks the signal stays high. Must be < period. e.g: if period = 100 and time_on = 60 the duty cycle is 60%
To simplify the complicated step of PWM calculation we provide a pre-calculated list.
The resulting pwm base frequency must be <1MHz!
Higher settings may damage the hardware!
The pwm function must be used with caution:
- The higher the frequency/duty cycle the higher the switching loss (power lost by generating the signal)
- As the IO-Modules pwm signal is powerful (high voltage and fast rise/fall times) electromagnetic compatibility must be kept in mind!
- Keep the cables as short as possible.
- Twisted cables are recommended.
- Keep pwm signals away from other cables.
- Use a braid-breaker (ferrite choke) close to the module on the cable.
- A shielded cable is possible but the shield should stay “floating” (do not connect to GND).
Request:
Method: POST
URL: <HOSTNAME>/api/io/<version>/<slot>/output/pwm
Parameters:
{
"pin": <int>,
"prescaler": <int>,
"time_on": <int>,
"period": <int>
}
Response:
Example
Request:
# 25.6kHz
curl http://localhost/api/io/1.0/3/output/pwm --header "Content-Type: application/json" --request POST --data '{"pin": 1, "prescaler": 2, "time_on": 312, "period": 625}'
Response:
3.1 - IO Module examples
Basic usage examples
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Please ensure nothing is connected to the hardware before running this examples!
Python examples
Example:
import requests
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login=("token", "")
hostname="localhost"
resp = requests.get("http://" + hostname + "/api/io/1.0/", auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
for device in response['devices']:
print("Input values for module on slot " + str(device['slot_number']) + ":")
resp = requests.get("http://" + hostname + "/api/io/1.0/" + str(device['slot_number']) + "/input/values", auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
for pin in response['pins']:
print(pin)
else:
print("Error response for slot " + str(device['slot_number']))
else:
print("Error response")
Output:
Input values for module on slot 3 :
{'pin': 1, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 2, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 3, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 4, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 5, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 6, 'pin_type': 'voltage_millivolt', 'value': 0}
Input values for module on slot 4 :
{'pin': 1, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 2, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 3, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 4, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 5, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 6, 'pin_type': 'voltage_millivolt', 'value': 0}
Input values for module on slot 6 :
{'pin': 1, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 2, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 3, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 4, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 5, 'pin_type': 'voltage_millivolt', 'value': 0}
{'pin': 6, 'pin_type': 'voltage_millivolt', 'value': 0}
Example:
import requests
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login=("token", "")
host_rest_api = "http://localhost/api/io/1.0/"
response = requests.get(host_rest_api, auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
for device in response['devices']:
slot_number = device['slot_number']
print("Output config for module on slot " + str(slot_number) + ":")
response = requests.get(host_rest_api + str(slot_number) + "/reset", auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device") # We do "write" requests so we need to get a defined state
request = {"config": [ # Power config is always configured for all pins!
{"rail": "5_volt", "current_milliampere": 10},
{"rail": "5_volt", "current_milliampere": 11},
{"rail": "5_volt", "current_milliampere": 12},
{"rail": "5_volt", "current_milliampere": 13},
{"rail": "5_volt", "current_milliampere": 14},
{"rail": "5_volt", "current_milliampere": 15}
]
}
response = requests.post(host_rest_api + str(slot_number) + "/power-management", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Power management configured")
request = {
"pin": 1,
"state": "high"
}
response = requests.post(host_rest_api + str(slot_number) + "/output/state", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Output 1 is set to HIGH")
else:
print("Failed changing output")
response = requests.get(host_rest_api + str(slot_number) + "/input/values", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
print("Voltage on output is: " + str(response['pins'][0]['value']) + " mV ")
else:
print("Failed getting values")
response = requests.get(host_rest_api + str(slot_number) + "/notification/1", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
print("Notification for pin: " + str(response))
else:
print("Failed getting notification")
request = {"reset": "yes"}
response = requests.post(host_rest_api + str(slot_number) + "/reset", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device after test")
print("")
else:
print("Error response for slot " + str(device['slot_number']))
else:
print("Error response")
Output:
Output config for module on slot 3:
Power management configured
Output 1 is set to HIGH
Voltage on output is: 4739 mV
Notification for pin: {'under_voltage_alert': False, 'high_voltage_alert': False, 'high_current_alert': False, 'custom_voltage_alert': False}
Successfully reset device after test
Output config for module on slot 4:
Power management configured
Output 1 is set to HIGH
Voltage on output is: 4739 mV
Notification for pin: {'under_voltage_alert': False, 'high_voltage_alert': False, 'high_current_alert': False, 'custom_voltage_alert': False}
Successfully reset device after test
Output config for module on slot 6:
Power management configured
Output 1 is set to HIGH
Voltage on output is: 4750 mV
Notification for pin: {'under_voltage_alert': False, 'high_voltage_alert': False, 'high_current_alert': False, 'custom_voltage_alert': False}
Successfully reset device after test
3.2 - PWM calculation
Configurations and calculation tools
PWM configurations (JSON)
Download optimized PWM settings as JSON structure
Please note that this list does not contain all possible configurations!
You can use the snippet below to search configs in your target frequency range.
Calculation snippet (Python)
def pwm_calc(period_hz):
BASE_CLK_HZ = 48 * 1000 * 1000
duty_cycle = 0.5
#print("Searching for: " + str(period_hz) + "Hz")
found = False
for prescaler in range(1, 0xffff, 1):
tick_time_hz = BASE_CLK_HZ / (prescaler + 1)
#print("Prescaled base frequency " + str(tick_time_hz) + "Hz")
if tick_time_hz < period_hz: # Return if prescaled tickrate is lower than the period
return (-1, None, None, None)
if tick_time_hz % 2 == 0: # Ignore uneven numbers
for t_period_cnt in range(1, 0xffff, 1):
t_period = (1 / (t_period_cnt / tick_time_hz))
if t_period == period_hz:
t_on = t_period_cnt * duty_cycle
print('Found ' + 'prescaler:' + str(prescaler) + ' t_period:' + str(t_period_cnt) + ' t_on: ' + str(
t_on)
+ ' for frequency (Hz) ' + str(t_period))
return period_hz, prescaler, t_period_cnt, t_on
# Select start and stop frequency in Hz. You can also specify the test step.
for i in range(1000,100000,100):
pwm_calc(i)
4 - Mainboard (BMC)
Mainboard RESTful API documentation
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Generic
Base URL:
<HOSTNAME>/api/bmc/<version>/
Version check and device selection
See Version check and device selection
Error response
See Error Response
Voltage
GET /voltage
Returns the voltage in millivolt.
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/voltage
Parameters:
Response:
{
"voltage_1v8": <mV>,
"voltage_rtc": <mV>
}
Example
Request:
curl http://localhost/api/bmc/1.0/0/voltage
Response:
{
"voltage_1v8": 1788,
"voltage_rtc": 2949
}
Temperature
GET /temperature
Returns the temperature in Celsius.
The “ntc_0” shows the temperature emitted by the SoC while the “ntc_1” shows the ambient temperature.
The unit is degree Celsius.
Location on the board:
ntc_0: close to the SoC/CPU
ntc_1: close to the buzzer/version information (temp. typically lower)
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/temperature
Parameters:
Response:
{
"ntc_0": <Temp. in Celsius (float)>,
"ntc_1": <Temp. in Celsius (float)>
}
Example
Request:
curl http://localhost/api/bmc/1.0/0/temperature
Response:
{
"ntc_0": 38.703,
"ntc_1": 29.587
}
Buzzer
POST /buzzer
Controls the integrated buzzer.
“mode” can be:
0 = Internal sounds are disabled
1 = Internal sounds are enabled
2 = Sound 1 played for duration
3 = Sound 2 played for duration
4 = Sound 3 played for duration
5 = Sound 4 played for duration
“duration” must be >= 1 and <= 1000 (milliseconds)
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/buzzer
Parameters:
{
"mode": <int>,
"duration": <ms>
}
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/buzzer --header "Content-Type: application/json" --request POST --data '{"mode": 4, "duration": 100}'
Response:
Watchdog
Controls the internal watchdog function which hard resets the device if the timeout expires.
GET /watchdog
Returns the timeout values in milliseconds.
timeout: current timeout setting
timeout_left: time left until reset
shutdown_timeout: time after the device is reset if a shutdown was initialized
emergency_mode: shows if the device is in emergency mode (storage corrupted, no r/w)
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog
Parameters:
Response:
{
"timeout": <ms>,
"timeout_left": <ms>,
"shutdown_timeout": <ms>,
"emergency_mode": <bool>
}
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog
Response:
{
"timeout": 0,
"timeout_left": 0,
"shutdown_timeout": 600000,
"emergency_mode": false
}
POST /watchdog
Enables the watchdog timeout. The timeout is disabled after reset if the config is not saved.
timeout: timeout setting in milliseconds
Value must be >= 1000 and <= 600000, 0 means disabled
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog --header "Content-Type: application/json" --request POST --data '{"timeout": 0}'
Response:
POST /watchdog/sw_shutdown_timeout
Changes the shutdown timeout. The timeout is always stored persistent.
timeout: timeout setting in milliseconds
Value must be >= 10000 and <= 600000
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog/sw_shutdown_timeout
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog/sw_shutdown_timeout --header "Content-Type: application/json" --request POST --data '{"timeout": 100000}'
Response:
POST /watchdog/shutdown
Starts the shutdown watchdog counter. This is the same procedure as triggered by the hardware switch.
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog/shutdown
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog/shutdown --header "Content-Type: application/json" --request POST --data '{"shutdown": "start"}'
Response:
GET /watchdog/alive
Resets the watchdog counter.
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog/alive
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog/alive
Response:
GET /watchdog/save
Saves the current timeout configuration persistent.
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/watchdog/save
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/watchdog/save
Response:
USB Hub
Controls the USB hub states.
GET /usbhub
Returns the states of all slots/ports and the hub itself.
state can be “enabled”, “disabled” or “not available”.
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usbhub
Parameters:
Response:
{
"hub_state": <state>,
"port_slot_0": <state>,
"port_slot_1": <state>,
"port_slot_2": <state>,
"port_slot_3": <state>,
"port_slot_4": <state>,
"port_slot_5": <state>,
"port_slot_6": <state>,
"port_slot_7": <state>,
}
Example
Request:
curl http://localhost/api/bmc/1.0/0/usbhub
Response:
{
"hub_state": "enabled",
"port_slot_0": "not available",
"port_slot_1": "not available",
"port_slot_2": "enabled",
"port_slot_3": "enabled",
"port_slot_4": "enabled",
"port_slot_5": "enabled",
"port_slot_6": "enabled",
"port_slot_7": "disabled",
}
GET /usbhub/devices
Returns all devices connected to the usb hub.
It maps the physical usb port number to the slot number.
Request:
Method: GET
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usbhub/devices
Parameters:
Response:
{
"devices": [
{
"slot": <int>,
"usb_port": <int>,
"manufacturer": <string>,
"product": <string>,
"serial_code": <string>,
"system_path": <string/path>
}
]
}
Example
Request:
curl http://localhost/api/bmc/1.0/0/usbhub/devices
Response:
{
"devices": [
{
"slot": 2,
"usb_port": 3,
"manufacturer": "NOREYA",
"product": "ETHERNET V1.1.0",
"serial_code": "099990002",
"system_path": "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3"
}
]
}
POST /usbhub
Enables or disables the USB Hub. The /reset command must be used to apply the settings.
The state is boolean and can be true or false.
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usbhub
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/usbhub --header "Content-Type: application/json" --request POST --data '{"state": true}'
Response:
POST /usbhub/slot/
Enables or disables the usb port on the slot.
The /usbhub/reset command must be used to apply the settings.
The state is boolean and can be true or false.
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usbhub/slot/<number>
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/usbhub/slot/7 --header "Content-Type: application/json" --request POST --data '{"state": true}'
Response:
POST /usbhub/reset
Resets the USB Hub and applies the saved setting.
CAUTION: On reset all USB devices are disconnected and may drop their connection!
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usbhub/reset
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/usbhub/reset --header "Content-Type: application/json" --request POST --data '{"reset": "yes"}'
Response:
USB Bootloader
POST /usb_bootloader
Enables the USB Bootloader which allows to access the internal storage (SDCARD/EMMC) via the USB port.
The mode is activated after next reset.
A host device must be connected via USB cable and the USB Bootloader must be activated within 90 seconds otherwise the device will reset to normal mode.
The bootloader tool can be found here.
“enabled” can be true or false
”timeout” must be <= 3600000 milliseconds
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/usb_bootloader
Parameters:
{
"enabled": <boolean>,
"timeout": <ms>,
}
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/usb_bootloader --header "Content-Type: application/json" --request POST --data '{"enabled": false, "timeout": 100000}'
Response:
Hard Reset
POST /hard_reset
Hard resets the device.
Request:
Method: POST
URL: <HOSTNAME>/api/bmc/<version>/<slot>/hard_reset
Parameters:
Response:
Example
Request:
curl http://localhost/api/bmc/1.0/0/hard_reset --header "Content-Type: application/json" --request POST --data '{"reset": "yes"}'
Response:
4.1 - BMC examples
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Python examples
Get temperature
Example:
import requests
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login=("token", "")
hostname="localhost"
resp = requests.get("http://" + hostname + "/api/bmc/1.0/", auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
for device in response['devices']:
print("Temperature values for BMC on slot " + str(device['slot_number']) + ":")
resp = requests.get("http://" + hostname + "/api/bmc/1.0/" + str(device['slot_number']) + "/temperature", auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
print("Temperature sensor next to SoC: " + str(response['ntc_0']) + "°C")
print("Temperature sensor ambient: " + str(response['ntc_1']) + "°C")
else:
print("Error response for slot " + str(device['slot_number']))
else:
print("Error response")
Output:
Temperature values for BMC on slot 0:
Temperature sensor next to SoC: 38.674°C
Temperature sensor ambient: 29.638°C
Watchdog configuration
Example:
import requests
import time
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login=("token", "")
hostname="localhost"
response = requests.get("http://" + hostname + "/api/bmc/1.0/", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
for device in response['devices']:
slot_number = device['slot_number']
print("Watchdog config for BMC on slot " + str(slot_number) + ":")
response = requests.get("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/reset", auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device") # We do "write" requests so we need to get a defined state
request = {"timeout": 2000 }
response = requests.post("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/watchdog", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Watchdog enabled with timeout " + str(request['timeout']) + 'ms')
response = requests.get("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/watchdog/alive", auth=login)
if response.status_code == requests.codes.ok:
print("Watchdog updated by /alive")
else:
print("Failed reseting watchdog")
print("Wait a second...")
time.sleep(1)
response = requests.get("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/watchdog", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
print("Time left until reset: " + str(response['timeout_left']) + ' ms')
else:
print("Failed getting watchdog status")
request = {"timeout": 0 }
response = requests.post("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/watchdog", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Watchdog disabled")
else:
print("Failed disabling watchdog")
response = requests.get("http://" + hostname + "/api/bmc/1.0/" + str(slot_number) + "/reset", auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device after test")
print("")
else:
print("Error response for slot " + str(device['slot_number']))
else:
print("Error response")
Output:
Watchdog config for BMC on slot 0:
Successfully reset device
Watchdog enabled with timeout 2000ms
Watchdog updated by /alive
Wait a second...
Time left until reset: 981 ms
Watchdog disabled
Successfully reset device after test
5 - Power Module
Power Module RESTful API documentation
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Generic
Base URL:
<HOSTNAME>/api/power/<version>/
Version check and device selection
See Version check and device selection
Error response
See Error Response
Source
GET /source
Returns the power sourcing capabilities of the device.
The source_* value shows the maximum power that can be consumed on this voltage rail in milliwatt.
The source_total value shows the maximum power all rails can consume together.
The efficiency_factor* can be used to calculate the power consumption including power dissipation.
e.g: Efficiency is 90% →value is 10W → calculated dissipation is 1W → total consumption is 11W
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/source
Parameters:
Response:
{
"source_3v3": <mW>,
"source_5v0": <mW>,
"source_12v": <mW>,
"source_total": <mW>,
"efficiency_factor_3v3": <int(%)>,
"efficiency_factor_5v0": <int(%)>,
"efficiency_factor_12v": <int(%)>
}
Example
Request:
curl http://localhost/api/power/1.0/1/source
Response:
{
"source_3v3": 17671,
"source_5v0": 22275,
"source_12v": 28750,
"source_total": 28750,
"efficiency_factor_3v3": 90,
"efficiency_factor_5v0": 90,
"efficiency_factor_12v": 100
}
Protection log
GET /protectionlog
Returns the internal protection table counters of the device.
If an error like an over voltage event occurs the counter is increased. It can be reset by the factory reset command.
Label explanation:
opp_protection_cnt = Sum of all counters
ovp* = Over voltage protection
uvp* = Under voltage protection
pmc_temperature = Power Management Controller temperature exceeded 125°C
total_power_overload = Total power limit of the device exceeded (see /source)
Voltage limits:
3V3 rail = 3.240V - 3.440V
5V0 rail = 4.608V - 5.202V
12V rail = 11.30V - 12.77V
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/protectionlog
Parameters:
Response:
{
"opp_protection_cnt": <int>,
"ovp_cnt_3v3": <int>,
"uvp_cnt_3v3": <int>,
"ovp_cnt_5v0": <int>,
"uvp_cnt_5v0": <int>,
"ovp_cnt_12v": <int>,
"uvp_cnt_12v": <int>,
"ocp_cnt_3v3": <int>,
"ocp_cnt_5v0": <int>,
"ocp_cnt_12v": <int>,
"pmc_temperature": <int>,
"total_power_overload": <int>
}
Example
Request:
curl http://localhost/api/power/1.0/1/protectionlog
Response:
{
"opp_protection_cnt": 0,
"ovp_cnt_3v3": 0,
"uvp_cnt_3v3": 0,
"ovp_cnt_5v0": 0,
"uvp_cnt_5v0": 0,
"ovp_cnt_12v": 0,
"uvp_cnt_12v": 0,
"ocp_cnt_3v3": 0,
"ocp_cnt_5v0": 0,
"ocp_cnt_12v": 0,
"pmc_temperature": 0,
"total_power_overload": 0
}
Stats
GET /stats
Returns the voltage and current statistics of the device.
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/stats
Parameters:
Response:
{
"voltage_3v3": <mV>,
"voltage_5v0": <mV>,
"voltage_12v": <mV>,
"current_3v3": <mA>,
"current_5v0": <mA>,
"current_12v": <mA>,
"limit_3v3": <mA>,
"limit_5v0": <mA>,
"limit_12v": <mA>
}
Example
Request:
curl http://localhost/api/power/1.0/1/stats
Response:
{
"voltage_3v3": 3301,
"voltage_5v0": 4936,
"voltage_12v": 11936,
"current_3v3": 762,
"current_5v0": 536,
"current_12v": 1,
"limit_3v3": 5950,
"limit_5v0": 4950,
"limit_12v": 2400
}
Limits
POST /limits
Enables the watchdog timeout. The timeout is disabled after reset if the config is not saved.
“limit_3v3” must be > 1000 and < 5950 mA
“limit_5v0” must be > 1000 and < 4950 mA
“limit_12v” must be > 100 and < 2400 mA
Request:
Method: POST
URL: <HOSTNAME>/api/power/<version>/<slot>/limits
Parameters:
{
"limit_3v3": <int>,
"limit_5v0": <int>,
"limit_12v": <int>
}
Response:
Example
Request:
curl http://localhost/api/power/1.0/1/limits --header "Content-Type: application/json" --request POST --data '{"limit_3v3": 5950, "limit_5v0": 4950, "limit_12v": 2400}'
Response:
Temperature
GET /temperature
Returns the temperature value of all sensors.
on_board_temp: Value from the NTC located next to the AC/DC converter
pmc_temp: Value from the PMCs internal sensor
The unit is degree Celsius.
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/temperature
Parameters:
Response:
{
"on_board_temp": <float>,
"pmc_temp": <float>
}
Example
Request:
curl http://localhost/api/power/1.0/1/temperature
Response:
{
"on_board_temp": 40.353,
"pmc_temp": 36.632
}
Fan
If the fan mode is changed it may take up to 10 seconds until it is applied by the firmware (to prevent fan vibrations).
fan_setting_mode and fan_current_mode can be compared to check the execution status.
GET /fan
Returns the fan statistics.
fan_forced: False means the fan is auto controlled by the firmware. True means the setting from fan_setting mode is applied.
fan_current_mode: Shows the mode currently in use (in auto and manual mode)
fan_setting_mode: Shows the mode which will be applied if fan_forced is True.
fan_*_mode values: 0, 20, 40, 60, 80, 100 (percent)
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/fan
Parameters:
Response:
{
"fan_forced": <bool>,
"fan_current_mode": <int>,
"fan_setting_mode": <int>
}
Example
Request:
curl http://localhost/api/power/1.0/1/fan
Response:
{
"fan_forced": false,
"fan_current_mode": 0,
"fan_setting_mode": 80
}
POST /fan
Changes the fan mode to the configured setting.
fan_*_mode values: 0, 20, 40, 60, 80, 100 (percent)
Request:
Method: POST
URL: <HOSTNAME>/api/power/<version>/<slot>/fan
Parameters:
{
"fan_forced": <bool>,
"fan_mode": <int>
}
Response:
Example
Request:
curl http://localhost/api/power/1.0/1/fan --header "Content-Type: application/json" --request POST --data '{"fan_forced": true, "fan_mode": 100}'
Response:
RPM
GET /fan/rpm
Returns the fan rounds-per-minute value.
It takes at least a second to update the value after the fan mode changed.
The typical maximum value is 5000 RPM +/- 15%.
Request:
Method: GET
URL: <HOSTNAME>/api/power/<version>/<slot>/fan/rpm
Parameters:
Response:
{
"enabled": <bool>,
"rpm": <int>
}
Example
Request:
curl http://localhost/api/power/1.0/1/fan/rpm
Response:
{
"enabled": false,
"rpm": 0
}
POST /fan/rpm
Changes the fan rounds-per-minute measurement status.
Request:
Method: POST
URL: <HOSTNAME>/api/power/<version>/<slot>/fan/rpm
Parameters:
{
"measurement_enabled": <bool>
}
Response:
Example
Request:
curl http://localhost/api/power/1.0/1/fan/rpm --header "Content-Type: application/json" --request POST --data '{"measurement_enabled": true}'
Response:
5.1 - Power Module examples
Basic usage examples
These examples are meant to be run on the device!
If you want to run them from a remote computer, you need to change “localhost” to the IP/hostname.
You will also need to generate an access token and use the “auth basic” method.
You may also want to use the secure protocol https://.
Python examples
Get voltage, current and power
Example:
import requests
base_url = "http://localhost/api/power/1.0/"
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login = ("token","")
resp = requests.get(base_url, auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
for device in response['devices']:
print("Voltage, current and power values for Power Module on slot " + str(device['slot_number']) + ":")
resp = requests.get(base_url + str(device['slot_number']) + "/stats", auth=login)
if resp.status_code == requests.codes.ok:
response = resp.json()
voltage_3v3 = round(response['voltage_3v3']/1000,3)
voltage_5v0 = round(response['voltage_5v0']/1000,3)
voltage_12v = round(response['voltage_12v']/1000,3)
current_3v3 = round(response['current_3v3']/1000,3)
current_5v0 = round(response['current_5v0']/1000,3)
current_12v = round(response['current_12v']/1000,3)
power_3v3 = round(voltage_3v3*current_3v3,3)
power_5v0 = round(voltage_5v0*current_5v0,3)
power_12v = round(voltage_12v*current_12v,3)
print("3V3 rail voltage/current/power: " + str(voltage_3v3) + "V * " + str(current_3v3) + "A = " + str(power_3v3) + "W")
print("5V0 rail voltage/current/power: " + str(voltage_5v0) + "V * " + str(current_5v0) + "A = " + str(power_5v0) + "W")
print("12V rail voltage/current/power: " + str(voltage_12v) + "V * " + str(current_12v) + "A = " + str(power_12v) + "W")
else:
print("Error response for slot " + str(device['slot_number']))
else:
print("Error response")
Output:
Voltage, current and power values for Power Module on slot 1:
3V3 rail voltage/current/power: 3.302V * 0.585A = 1.932W
5V0 rail voltage/current/power: 4.938V * 0.397A = 1.96W
12V rail voltage/current/power: 11.945V * 0.002A = 0.024W
Fan control
Example:
import requests
import time
base_url = "http://localhost/api/power/1.0/"
# For tokens see http://noreya-nexus.local/nexuscontrolui/system/settings#access-token
login = ("token","")
def check_fan(slot_number):
response = requests.get(base_url + str(slot_number) + "/fan", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
if response['fan_forced']:
print("Fan is controlled by the driver")
else:
print("Fan is controlled by the firmware")
print("Fan speed is: " + str(response['fan_current_mode']) + '%')
print("Fan setting is: " + str(response['fan_setting_mode']) + '%')
if (response['fan_current_mode'] != response['fan_setting_mode']) and response['fan_forced']:
print ("Fan setting is going to be applied within 10 seconds")
return True
elif response['fan_forced']:
print ("Fan setting applied!")
print ("")
return False
else:
raise RuntimeError("Could not get fan status")
response = requests.get(base_url, auth=("", ""))
if response.status_code == requests.codes.ok:
response = response.json()
for device in response['devices']:
slot_number = device['slot_number']
print("Fan control for Power Module on slot " + str(slot_number) + ":")
response = requests.get(base_url + str(slot_number) + "/reset", auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device") # We do "write" requests so we need to get a defined state
request = {"measurement_enabled": True}
response = requests.post(base_url + str(slot_number) + "/fan/rpm", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Fan rpm measurement enabled")
else:
print("Enabling RPM measurement failed")
check_fan(slot_number)
print("")
request = {"fan_forced": True, "fan_mode": 100}
response = requests.post(base_url + str(slot_number) + "/fan", json=request, auth=login)
if response.status_code == requests.codes.ok:
print("Fan speed set to 100%")
while check_fan(slot_number): # Worst case it can take 10 seconds until the mode changes!
time.sleep(1)
else:
print("Could not set fan mode")
time.sleep(2) # It takes at least a second before the RPM value is available
response = requests.get(base_url + str(slot_number) + "/fan/rpm", auth=login)
if response.status_code == requests.codes.ok:
response = response.json()
print("Fan rounds-per-minutes: " + str(response['rpm']))
else:
print("Could not get fan rpm value")
response = requests.get(base_url + str(slot_number) + "/reset", auth=login)
if response.status_code == requests.codes.ok:
print("Successfully reset device")
else:
print("Error response")
Output:
Fan control for Power Module on slot 1:
Successfully reset device
Fan rpm measurement enabled
Fan is controlled by the firmware
Fan speed is: 0%
Fan setting is: 100%
Fan speed set to 100%
Fan is controlled by the driver
Fan speed is: 0%
Fan setting is: 100%
Fan setting is going to be applied within 10 seconds
Fan is controlled by the driver
Fan speed is: 0%
Fan setting is: 100%
Fan setting is going to be applied within 10 seconds
Fan is controlled by the driver
Fan speed is: 0%
Fan setting is: 100%
Fan setting is going to be applied within 10 seconds
Fan is controlled by the driver
Fan speed is: 100%
Fan setting is: 100%
Fan setting applied!
Fan rounds-per-minutes: 4500
Successfully reset device
6 - Versioning
API versioning schema
The following versioning schema is used for all APIs.
Base URL
<HOSTNAME>/api/<module>/<version>
Examples:
<HOSTNAME>/api/power/0.1/
<HOSTNAME>/api/io/1.0/
<HOSTNAME>/api/bmc/0.11/
Versioning schema
The versioning schema follows the https://semver.org/ guidelines (MAJOR.MINOR.PATCH).
MAJOR
The major number is increased if the API has incompatible changes.
This version MUST be checked by all clients before using the API.
MINOR
The minor number indicates that additional endpoints have been added to the API.
PATCH
The patch number is incremented if non compatibility breaking changes are made.
It is not part of the URL but can be checked by using the /version endpoint.