With ClearBlade IoT Core, you can monitor each connected device’s state. The device reports it as binary data. Device state updates are typically triggered by a device change — a configuration update from ClearBlade IoT Core or a similar change from another external source, such as a firmware update.
Device state differs from device configuration. Configuration data is sent to the device from ClearBlade IoT Core. The device sends state data to ClearBlade IoT Core. Configuration is an external instruction, and state is an internal representation.
ClearBlade IoT Core can help you answer questions about configuration and state: What does the device think it should be doing? How does that compare to the most recent device configuration?
Limits
State updates are limited to 1 update per second per device. However, for best results, the device state should be updated much less often — at most, once every 10 seconds.
Reporting device state
MQTT bridge
To report the state to ClearBlade IoT Core through the MQTT bridge, publish messages to the /devices/DEVICE_ID/state
MQTT topic. You can select a Cloud Pub/Sub topic to store state events when you create or update a registry.
For more details, see Publishing over the MQTT bridge.
HTTP bridge
To report the state to ClearBlade IoT Core through the HTTP bridge, devices should use a setState
request. The binary state data is passed in the request’s body as a base64-encoded string.
For more details, see Publishing over the HTTP bridge.
Getting device state data
This section explains how to get the state data reported to ClearBlade IoT Core by devices (devices cannot read state data from the cloud).
State data is returned in binary format. State data may have a different structure than the configuration data that triggers the state change.
For example, suppose you have a device with several fans. Your configuration data might be a JSON object containing a Boolean that enables or disables cooling:
{ 'cooling': true}
But the device's state data might include diagnostic information, as well as the fan data that you'd expect to see in response to a 'cooling'
change:
{ 'fan1_target_rpm': 1000, 'fan2_target_rpm': 1200, 'firmware_version': '1.2.3b'}
The device's firmware_version
is unrelated to the configuration data but returns its state's full internal representation. This example illustrates how the device state can help debug and confirm that devices have acknowledged specific configurations.
Retrieving the device state from a device registry code examples
Use the Device states.list method to get the most recent device states (up to 10). Each Device
resource has a DeviceState
field that contains the state most recently received from the device. The DeviceRegistry
resource has a StateNotificationConfig field that can specify a state notification Cloud Pub/Sub topic when creating or updating a registry.
Node.js
// const cloudRegion = 'us-central1'; // const deviceId = 'my-device'; // const projectId = 'adjective-noun-123'; // const registryId = 'my-registry'; import { DeviceManagerClient } from '@clearblade/iot'; const iotClient = new DeviceManagerClient({ // optional auth parameters. }); async function listDeviceStates() { const devicePath = iotClient.devicePath(projectId, cloudRegion, registryId, deviceId); const [response] = await iotClient.listDeviceStates({ name: devicePath }); const states = response.deviceStates; if (states.length === 0) { console.log(`No States for device: ${deviceId}`); } else { console.log(`States for device: ${deviceId}`); } for (let i = 0; i < states.length; i++) { const state = states[i]; console.log('State:', state, '\nData:\n', state.binaryData.toString('utf8')); } } listDeviceStates();
C#
{ logger.LogInformation("Get a device"); string name = "projects/developmentenv/locations/us-central1/registries/Sample-New-Registry/Devices/Sample-New-Device"; var result = await mClient.GetDevice(4, name); if (!result.Item1 || (result.Item2 == null)) logger.LogError("Failed to get a device"); else { logger.LogInformation("Successfully obtained the device"); } }
Python
import os from clearblade.cloud import iot_v1 def list_device_states(): project_id = 'YOUR_PROJECT_ID' cloud_region = 'us-central1' registry_id = 'your-registry-id' device_id = 'your-device-id' client = iot_v1.DeviceManagerClient() device_path = client.device_path(project_id, cloud_region, registry_id, device_id) request = iot_v1.ListDeviceStatesRequest( name=device_path, numStates=0 ) response = client.list_device_states(request=request) states = response.device_states if (len(states) == 0): print(f"No states for device: {device_id}") else: print("States:") for state in states: if state.binary_data is not None: print(f"updateTime: {state.update_time}; binaryData: {state.binary_data}") os.environ["CLEARBLADE_CONFIGURATION"] = "/path/to/your-credentials.json" list_device_states()
Go
// getDeviceStates retrieves and lists device states. func getDeviceStates(w io.Writer, projectID string, region string, registryID string, device string) ([]*iot.DeviceState, error) { // Authorize the client using Application Default Credentials. // See https://g.co/dv/identity/protocols/application-default-credentials ctx := context.Background() service, err := iot.NewService(ctx) if err != nil { return nil, err } path := fmt.Sprintf("projects/%s/locations/%s/registries/%s/devices/%s", projectID, region, registryID, device) response, err := service.Projects.Locations.Registries.Devices.States.List(path).Do() if err != nil { return nil, err } fmt.Fprintln(w, "Successfully retrieved device states!") for _, state := range response.DeviceStates { fmt.Fprintf(w, "%s : %s\n", state.UpdateTime, state.BinaryData) } return response.DeviceStates, nil }