123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- #pragma once
- // This is the description of the Improv Wi-Fi protocol using a serial port.
- // The device needs to be connected to the computer via a USB/UART serial port.
- // The protocol has two actors: the Improv service running on the gadget and the Improv client.
- // The Improv service will receive Wi-Fi credentials from the client via the serial connection.
- // The Improv client asks for the current state and sends the Wi-Fi credentials.
- // =========================================================================================
- // Packet format
- // ======================================
- // Byte Purpose
- // ---- -------------------------------
- // 1-6 Header will equal IMPROV
- // 7 Version CURRENT VERSION = 1
- // 8 Type (see below)
- // 9 Length
- // 10...X Data
- // X + 10 Checksum
- // =========================================================================================
- // Packet types
- // ======================================
- // Type Description Direction
- // ---- ------------ -----------------
- // 0x01 Current state Device to Client
- // 0x02 Error state Device to Client
- // 0x03 RPC Command Device to Client
- // 0x04 RPC Result Client to Device
- typedef enum {
- IMPROV_PACKET_TYPE_CURRENT_STATE = 0x01,
- IMPROV_PACKET_TYPE_ERROR_STATE = 0x02,
- IMPROV_PACKET_TYPE_RPC = 0x03,
- IMPROV_PACKET_TYPE_RPC_RESPONSE = 0x04
- } ImprovSerialType_t;
- // =========================================================================================
- // Packet: Current State
- // ======================================
- // Type: 0x01
- // Direction: Device to Client
- // --------------------------------------
- // The data of this packet is a single byte and contains the current status of the provisioning
- // service. It is to be written to any listening clients for instant feedback.
- // Byte Description
- // 1 current state
- // The current state can be the following values:
- // Value State Purpose
- // ----- ------------------ -----------------------------------------
- // 0x02 Ready (Authorized) Ready to accept credentials.
- // 0x03 Provisioning Credentials received, attempt to connect.
- // 0x04 Provisioned Connection successful.
- typedef enum {
- IMPROV_STATE_READY_AUTHORIZED = 0x02,
- IMPROV_STATE_PROVISIONING = 0x03,
- IMPROV_STATE_PROVISIONED = 0x04,
- } ImprovState_t;
- // =========================================================================================
- // Packet: Error state
- // ======================================
- // Type: 0x02
- // Direction: Device to client
- // --------------------------------------
- // The data of this packet is a single byte and contains the current status of the
- // provisioning service. Whenever it changes the device needs to sent it to any listening
- // clients for instant feedback.
- // Byte Description
- // 1 error state
- // Error state can be the following values:
- // Value State Purpose
- // ----- ------------------ -----------------------------------------
- // 0x00 No error This shows there is no current error state.
- // 0x01 Invalid RPC packet RPC packet was malformed/invalid.
- // 0x02 Unknown RPC command The command sent is unknown.
- // 0x03 Unable to connect The credentials have been received and an attempt to connect
- // to the network has failed.
- // 0xFF Unknown Error
- typedef enum {
- IMPROV_ERROR_NONE = 0x00,
- IMPROV_ERROR_INVALID_RPC = 0x01,
- IMPROV_ERROR_UNKNOWN_RPC = 0x02,
- IMPROV_ERROR_UNABLE_TO_CONNECT = 0x03,
- IMPROV_ERROR_NOT_AUTHORIZED = 0x04,
- IMPROV_ERROR_UNKNOWN = 0xFF,
- } ImprovError_t;
- // =========================================================================================
- // Packet: RPC Command
- // Type: 0x03
- // Direction: Client to device
- // --------------------------------------
- // This packet type is used for the client to send commands to the device. When an RPC
- // command is sent, the device should sent an update to the client to set the error state to
- // 0 (no error). The response will either be an RPC result packet or an error state update.
- // Byte Description
- // ----- ---------------------
- // 1 Command (see below)
- // 2 Data length
- // 3...X Data
- typedef enum {
- IMPROV_CMD_UNKNOWN = 0x00,
- IMPROV_CMD_WIFI_SETTINGS = 0x01,
- IMPROV_CMD_GET_CURRENT_STATE = 0x02,
- IMPROV_CMD_GET_DEVICE_INFO = 0x03,
- IMPROV_CMD_GET_WIFI_NETWORKS = 0x04,
- IMPROV_CMD_BAD_CHECKSUM = 0xFF,
- } ImprovCommand_t;
- // ======================================
- // RPC Command: Send Wi-Fi settings
- // Submit Wi-Fi credentials to the Improv Service to attempt to connect to.
- // Type: 0x03
- // Command ID: 0x01
- // Byte Description
- // ----- ----------------
- // 1 command (0x01)
- // 2 data length
- // 3 ssid length
- // 4...X ssid bytes
- // X password length
- // X...Y password bytes
- // Example: SSID = MyWirelessAP, Password = mysecurepassword
- // 01 1E 0C {MyWirelessAP} 10 {mysecurepassword}
- // This command will generate an RPC result. The first entry in the list is an URL to
- // redirect the user to.
- // If there is no URL, omit the entry or add an empty string.
- // ======================================
- // RPC Command: Request current state
- // Sends a request for the device to send the current state of improv to the client.
- // Type: 0x03
- // Command ID: 0x02
- // Byte Description
- // ----- ----------------
- // 1 command (0x02)
- // 2 data length (0)
- // This command will trigger at least one packet, the Current State (see above) and if
- // already provisioned,
- // the same response you would get if device provisioning was successful (see below).
- // ======================================
- // RPC Command: Request device information
- // Sends a request for the device to send information about itself.
- // Type: 0x03
- // Command ID: 0x03
- // Byte Description
- // ----- ----------------
- // 1 command (0x02)
- // 2 data length (0)
- // This command will trigger one packet, the Device Information formatted as a RPC result.
- // This result will contain at least 4 strings.
- // Order of strings: Firmware name, firmware version, hardware chip/variant, device name.
- // Example: ESPHome, 2021.11.0, ESP32-C3, Temperature Monitor.
- // ======================================
- // RPC Command: Request scanned Wi-Fi networks
- // Sends a request for the device to send the Wi-Fi networks it sees.
- // Type: 0x03
- // Command ID: 0x04
- // Byte Description
- // ----- ----------------
- // 1 command (0x02)
- // 2 data length (0)
- // This command will trigger at least one RPC Response. Each response will contain at
- // least 3 strings.
- // Order of strings: Wi-Fi SSID, RSSI, Auth required.
- // Example: MyWirelessNetwork, -60, YES.
- // The final response (or the first if no networks are found) will have 0 strings in the body.
- // =========================================================================================
- // Packet: RPC Result
- // ======================================
- // Type: 0x04
- // Direction: Device to client
- // --------------------------------------
- // This packet type contains the response to an RPC command. Results are returned as a list
- // of strings. An empty list is allowed.
- // Byte Description
- // ----- ----------------
- // 1 Command being responded to (see above)
- // 2 Data length
- // 3 Length of string 1
- // 4...X String 1
- // X Length of string 2
- // X...Y String 2
- // ... etc
- static const uint8_t CAPABILITY_IDENTIFY = 0x01;
- static const uint8_t IMPROV_SERIAL_VERSION = 1;
- #ifndef FREE_AND_NULL
- #define FREE_AND_NULL(x) if(x) { free(x); x=NULL; }
- #endif
- #ifndef ENUM_TO_STRING
- #define ENUM_TO_STRING(g) \
- case g: \
- return STR(g); \
- break;
- #endif
- typedef struct {
- ImprovCommand_t command;
- char * ssid;
- char * password;
- } ImprovCommandStruct_t;
- typedef struct {
- char * ssid;
- char * rssi;
- char * auth_req; // YES/NO
- } ImprovAPListStruct_t;
- #define IMPROV_AP_STRUCT_NUM_STR 3
- typedef struct {
- char * firmware_name;
- char * firmware_version;
- char * hardware_chip_variant;
- char * device_name;
- char * nullptr;
- } ImprovDeviceInfoStruct_t;
- #define IMPROV_DEVICE_INFO_NUM_STRINGS 4
- typedef bool (*improv_command_callback_t)(ImprovCommandStruct_t *cmd);
- typedef void (*on_error_callback_t)(ImprovError_t error);
- typedef bool (*improv_send_callback_t)(uint8_t * buffer, size_t length);
- typedef struct {
- int index ;
- improv_command_callback_t callback ;
- } callback_table_t;
- void improv_parse_data(ImprovCommandStruct_t * improv_command, const uint8_t *data, size_t length, bool check_checksum) ;
- bool improv_parse_serial_byte(size_t position, uint8_t byte, const uint8_t *buffer,improv_command_callback_t callback, on_error_callback_t on_error);
- bool parse_improv_serial_line( const uint8_t *buffer);
- void improv_set_send_callback(improv_send_callback_t callback );
- bool improv_set_callback(ImprovCommand_t command, improv_command_callback_t callback );
- bool improv_wifi_list_allocate(size_t num_entries);
- bool improv_wifi_list_add(const char * ssid, int8_t rssi, bool auth_req );
- bool improv_wifi_list_send( );
- size_t improv_wifi_get_wifi_list_count();
- bool improv_send_device_info( const char * firmware_name, const char * firmware_version, const char * hardware_chip_variant, const char * device_name);
- uint8_t * improv_build_response(ImprovSerialType_t command, const char * datum, size_t len, size_t * out_len);
- uint8_t * improv_build_rpc_response(ImprovCommand_t command, const char ** results, size_t num_strings, size_t * out_len);
- bool improv_send_current_state(ImprovState_t state);
- bool improv_send_error(ImprovError_t error);
- const char * improv_get_error_desc(ImprovError_t error);
- const char * improv_get_command_desc(ImprovCommand_t command);
- bool improv_send_device_url( ImprovCommand_t from_command, const char * url);
- // Improv Wi-Fi – Contact – GitHub
- // Improv is an initiative by ESPHome & Home Assistant.
- // Development funded by Nabu Casa.
|