| title | Advanced Information |
|---|---|
| permalink | /advanced |
| nav_order | 7 |
Your contributions to the project are welcome and encouraged. Many excellent features of PiFire were contributions from users just like you. If you want to dive deeper into PiFire and possibly develop a pull-request on GitHub, please follow the below guidelines:
- Pull Requests: When submitting PR's please make sure they are submitted on the development branch of PiFire. All other PRs will be rejected unless you have explicit permission from the project owner.
- Do no harm: Make sure you are not breaking others user experience when submitting a PR. Ideally, isolate your feature / code into something new. PiFire was designed with certain aspects to be modular so that you can create a new display, distance sensor, controller, etc. without harming existing configurations. Please do your best to follow these principles.
- Document your Code - Please document your code to the best of your ability so that the reviewers can understand what you are doing.
- Test your Changes - Try to test your changes extensively to ensure compatibility with many configurations. While it may not be possible in every case, it is very helpful to do some validation runs on your code to make sure it is stable before making pull requests.
For the more adventurous of you, who want to tweak, extend and improve PiFire for your purposes, I've tried to architect PiFire in a way to make it friendly to use on different hardware.
You may have noticed that we have a few modules that can be used interchangeably with a common API. Modules are organized into directories which are collections of modules that can be used for different purposes:
- Platform (grillplat/xxxx.py): Used for Input / Output with grill itself. (i.e. Any Inputs (Buttons / Switches) and Relay Outputs for Fan, Auger, Igniter, etc.)
- Probes (probes/xxxx.py): Used to get data for the different temperature probes and devices.
- Display (display/xxxx.py): Interface for the display / input. Used to control and print information to the display.
- Distance / Hopper Level (distance/xxxx.py): Interface for getting hopper level input information - used by the pellet manager.
- Controller (controller/xxxx.py): Controller logic, such as PID, fuzzy logic or machine learning, etc.
Organizing modules in this way allows developers to create their own modules to support different ADC devices, Display Devices, and Grill configurations. It's recommended to look at the existing modules to understand their construction. Specifically looking at the prototype modules may be enlightening to get an idea of how they work.
Most of the above module types have a prototype version (i.e. prototype.py) which is used to test PiFire on other platforms (i.e. Windows, Linux or MacOS). Input and output is simulated, and can be used in conjunction with your own modules for testing purposes.
When prototyping functionality it's helpful to run control.py in one process and the app.py in another process. This way you can access the PiFire webui via your web browser of choice and monitor the console output of the control.py script in a separate window.
PiFire offers a basic API to adjust settings or to control the system over the a network. This API is used by the dashboard javascript to control the grill, which can be used as a reference for others build apps, dashboards or even other hardware that interfaces with the system.
There are two levels of API commands that are available. High level API commands such as Get, Set and Cmd are provided as a very simple interface to interact with the PiFire system. These have simple to access commands that can be executed with a URL directly. Low level API commands are provided to allow power users to directly manipulate settings/configuration/control on the system either with specific changes or in bulk writes & reads.
High Level API commands were introduced in v1.7.0 of PiFire. High Level API commands can be executed with only the URL. These commands can be called via POST or GET. Commands will always return the basic structure in the format below:
{
"data" : {},
"message" : "Command was accepted successfully.",
"result" : "OK"
}Any data returned will be in the "data" structure (described in commands below). The message will provide any additional details about the command, especially errors if any occurred. The result will either be 'OK' or 'ERROR'.
/api/get/current
Returns (Example):
{
"AUX": {},
"F": {
"Probe1": 204,
"Probe2": 206
},
"NT": {
"Grill": 0,
"Probe1": 0,
"Probe2": 0
},
"P": {
"Grill": 518
},
"PSP": 0,
"TS": 1707345482984
}/api/get/temp/{probe label}
Notes: {probe_label} must be a valid probe label (not the actual probe name) which can be discovered by executing get current.
Returns:
{
'temp' : <probe temperature>
}/api/get/mode
Returns (example):
{
"mode" : "Stop"
}/api/get/hopper
Notes: Returns the hopper pellet level in percentage.
Returns (example):
{
"hopper" : 75
}/api/get/timer
Returns (example):
{
"start" : 0,
"paused" : 0,
"end" : 0,
"shutdown" : false,
"keep_warm" : false,
}/api/get/notify
Returns (example abbreviated):
[
{
"eta": null,
"keep_warm": false,
"label": "Grill",
"name": "GrillMain",
"req": false,
"shutdown": false,
"target": 0,
"type": "probe"
},
...
{
"keep_warm": false,
"label": "Hopper",
"last_check": 0,
"req": true,
"shutdown": false,
"type": "hopper"
}
]/api/get/status
Returns (Example):
{
"display_mode": "Stop",
"lid_open_detected": false,
"lid_open_endtime": 0,
"mode": "Stop",
"name": "Development",
"outpins": {
"auger": false,
"fan": false,
"igniter": false,
"power": false
},
"p_mode": 0,
"prime_amount": 0,
"prime_duration": 0,
"s_plus": false,
"shutdown_duration": 10,
"start_duration": 30,
"start_time": 0,
"startup_timestamp": 0,
"status": "",
"ui_hash": 5734093427135650890,
"units": "F"
}/api/set/psp/{integer/float temperature}
/api/set/mode/{mode}
/api/set/mode/prime/{prime amount in grams}[/{next mode}]
/api/set/mode/hold/{integer/float temperature}
Where mode/next mode = 'startup', 'smoke', 'shutdown', 'stop', 'reignite', 'monitor', 'error', 'manual'
/api/set/pmode/{pmode value}
Note: PMode value is between 0-9
/api/set/splus/{true/false}
True = Smoke Plus Enabled, False = Smoke Plus Disabled
/api/set/notify/{object}/req/{true/false}
/api/set/notify/{object}/target/{value}
/api/set/notify/{object}/shutdown/{true/false}
/api/set/notify/{object}/keep_warm/{true/false} {object} = probe label, 'Timer', or 'Hopper' Note that target/{value} is not valid for Timer or Hopper
/api/set/pwm/{true/false} True = Enable PWM Control, False = Disable PWM Control PiFire must be configured for the PWM platform or this will do nothing
/api/set/duty_cycle/{percent} Must be a value in 0-100 percent
/api/set/tuning_mode/{true/false} True = Tuning mode enabled, False = Tuning mode disabled
/api/set/timer/start/{seconds}
/api/set/timer/pause
/api/set/timer/stop
/api/set/timer/shutdown/{true/false}
/api/set/timer/keep_warm/{true/false}Start will default to 60s unless a time is specified. Timer duration should be in seconds.
Shutdown True = Grill will shutdown when timer expires
Keep Warm True = Grill will go to Hold Mode (keep warm temperature specified in settings) when timer expires.
{: .warning }
System must already be in Manual mode (see set/mode command)
/api/set/manual/power/{true/false}
/api/set/manual/igniter/{true/false}
/api/set/manual/fan/{true/false}
/api/set/manual/auger/{true/false}
/api/set/manual/pwm/{speed}True = On, False = Off
/api/set/units/{F/C}
Set the global units to F (Fahrenheit) or C (Celsius)
/api/cmd/restartRestarts the scripts/server without reboot.
/api/cmd/rebootReboots the server.
/api/cmd/shutdownShutdown the server.
The Low Level API has changed since v1.5.0 to include more flexibility of probe definitions and types.
For the low level commands, you must specify the correct request type (either GET or POST) for these commands.
GET
/api/settingsDumps all of the current settings from settings.json in JSON format
GET
/api/controlDumps all of the current control from control.json in JSON format
GET
/api/hopperDumps data regarding the hopper level and what pellets are currently loaded. For example:
{
"hopper_level":100,
"hopper_pellets":"Generic Alder"
}GET
/api/currentDumps JSON of some key current activity, for ex:
{
"current":
{
"F": {
"Probe1":114,
"Probe2":90,
"Probe3":151
},
"NT": {
"Grill":0,
"Probe1":0,
"Probe2":0,
"Probe3":0
},
"P": {
"Grill":227
},
"PSP":0
},
"notify_data": [
{
"keep_warm":false,
"label":"Grill",
"name":"Grill",
"req":false,
"shutdown":false,
"target":0,
"type":"probe"
},
{
"keep_warm":false,
"label":"Probe1",
"name":"Probe-1",
"req":false,
"shutdown":false,
"target":0,
"type":"probe"
},
{
"keep_warm":false,
"label":"Probe2",
"name":"Probe-2",
"req":false,
"shutdown":false,
"target":0,
"type":"probe"
},
{
"keep_warm":false,
"label":"Probe3",
"name":"Probe-3",
"req":false,
"shutdown":false,
"target":0,
"type":"probe"
},
{
"keep_warm":false,
"label":"Timer",
"req":false,
"shutdown":false,
"type":"timer"
},
{
"keep_warm":false,
"label":"Hopper",
"last_check":0,
"req":true,
"shutdown":false,
"type":"hopper"
}
],
"status": {
"display_mode":"Startup",
"lid_open_detected":false,
"lid_open_endtime":0,
"mode":"Startup",
"name":"",
"outpins": {
"auger":false,
"fan":true,
"igniter":true,
"power":true
},
"p_mode":5,
"prime_amount":0,
"prime_duration":0,
"s_plus":false,
"shutdown_duration":60,
"start_duration":240,
"start_time":1699310434.8917897,
"status":"active",
"ui_hash":1382036478,
"units":"F"
}
}These commands all you to change some or all of the settings/control data directly.
You do not have to replicate all of the data in these data structures when you POST, and only need to include the data that you are modifying. The exception to this rule is if you are modifying a LIST. In the case where you are modifying a list, you must read/modify/write the entire list. Example may be in control['notify_data'] which is a list, you may only want to edit a single entry. You may need to read the entire list, modify the data, and then write the entire list back.
POST
/api/settingsChange any settings data from settings.json. Post format identical to the format of the settings.json file. For ex:
{ "globals" : { "grill_name" : "Smokey the Bear" } }POST
/api/controlChange any control data from control.json. Post format identical to the format of the control data structure in redis. For ex:
{ "updated" : true, "mode" : "Startup" } This code will change the mode to 'Startup' and by setting the 'updated' key to 'true', will tell the control script to check for the mode change.