Fixed input option via api

Hi

I have a few basic Shelly H&T to monitor temperature and humidity. they run on a small battery and are very limited in its capabilities.
Its a fixed url option string that it will send along;
?hum=60&temp=25.00&id=shellyht-xxxxxx
You can specify an endpoint, like http://192.168.0.20/sensor.php and it will become
http://192.168.0.20/sensor.php?hum=60&temp=25.00&id=shellyht-xxxxxx

I created the following PHP script(and made it public via apache), to just forward data into emonCMS, but i was wonderring, if there was a build-in way of dealing with devices that cannot add required metadata (like apikey), and where the data is fixed in its format.

<?php
$humidity = isset($_GET['hum']) ? floatval($_GET['hum']) : null;
$temperature = isset($_GET['temp']) ? floatval($_GET['temp']) : null;
$device_id = isset($_GET['id']) ? $_GET['id'] : null;


$humidity = floatval($humidity);
$temperature = floatval($temperature);
$device_id = htmlspecialchars($device_id, ENT_QUOTES, 'UTF-8');

switch ($device_id) {
    case 'shellyht-45DF30':
        if ($humidity !== null) {
            file_get_contents("http://192.168.0.20/feed/post.json?id=9&apikey=APIKEY&value=$humidity");
        }
        if ($temperature !== null) {
             file_get_contents("http://192.168.0.20/feed/post.json?id=8&apikey=APIKEY&value=$temperature");
        }
        break;

    case 'shellyht-yyyyyy':
        if ($humidity !== null) {
            file_get_contents("http://192.168.0.122/feed/post.json?id=10&value=$humidity");
        }
        if ($temperature !== null) {
            file_get_contents("http://192.168.0.122/feed/post.json?id=11&value=$temperature");
        }
        break;

    default:
        // Optional: log unknown device or do nothing
        error_log("Unknown device ID: $device_id");
        break;
}
?>

Welcome, Morten, to the OEM forum.

I’m no expert on the internals of emonCMS, but I’m almost certain the answer is a firm no. I think you probably already have the best solution. A fundamental concept of emonCMS is it can accept data from anywhere worldwide provided your ISP and router/firewall allows (from its origins in the open emoncms.org) and it relies entirely on the APIkey for authority to accept and process the data. It doesn’t have a way to in effect accept “id=shellyht-xxxxxx” as the APIkey.

It might be possible to create an Interfacer for emonHub that does what you need - maybe @TrystanLea, you can confirm?

Thanks @Robert.Wall , @MortenKK your solution looks like a good approach. Perhaps an extension of this could be to create an emoncms shelly module, e.g:

emoncms/Modules/shelly

with a simple controller file shelly_controller.php:

This example loads the emoncms modules directly involved with processing input data and registers the data as inputs on the local emoncms inputs page for user 1 with no authentication..

<?php

// no direct access
defined('EMONCMS_EXEC') or die('Restricted access');

function shelly_controller()
{
    global $mysqli, $session, $route, $redis, $settings, $device, $user;

    // Initialize required Emoncms modules
    require_once "Modules/feed/feed_model.php";
    $feed = new Feed($mysqli,$redis, $settings["feed"]);
    require_once "Modules/input/input_model.php";
    $input = new Input($mysqli,$redis, $feed);
    require_once "Modules/process/process_model.php";
    $process = new Process($mysqli,$input,$feed,$user->get_timezone($session['userid']));

    if (!$device) {
        if (file_exists("Modules/device/device_model.php")) {
            require_once "Modules/device/device_model.php";
            $device = new Device($mysqli,$redis);
        }
    }
    require_once "Modules/input/input_methods.php";
    $inputMethods = new InputMethods($mysqli,$redis,$user,$input,$feed,$process,$device);

    $result = false;

    if ($route->action == 'data')
    {
        $route->format = 'json'; // Set response format to JSON

        // Get device ID
        $device_id = isset($_GET['id']) ? $_GET['id'] : null;
        
        // Validate device ID
        if ($device_id === null) {
            return array('success' => false, 'message' => 'Device ID required');
        }
        
        // Sanitize device_id
        $device_id = htmlspecialchars($device_id, ENT_QUOTES, 'UTF-8');
        
        // Get all GET parameters except 'id' and build data array
        $data = array();
        foreach ($_GET as $key => $value) {
            if ($key !== 'id' && $key !== 'q') {
                // Convert numeric values to floats, keep strings as strings
                if (is_numeric($value)) {
                    $data[$key] = floatval($value);
                } else {
                    $data[$key] = htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
                }
            }
        }
        
        // Skip if no data to send
        if (empty($data)) {
            return array('success' => false, 'message' => 'No data parameters provided');
        }
        
        // Process data directly using Emoncms InputMethods
        $userid = 1;
        $time = time();
        $nodeid = $device_id;
        $inputs = $data;
        
        $process_result = $inputMethods->process_node($userid, $time, $nodeid, $inputs);
        
        $result = array(
            'userid' => $userid,
            'time' => $time,
            'nodeid' => $nodeid,
            'data' => $data,
            'process_result' => $process_result
        );
    }

    return array('content' => $result);
}