Skip to content

Commit

Permalink
implement enhanced app for shelly plugs
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Schmitz committed Nov 23, 2023
1 parent d2c83d1 commit 1ca76bb
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 0 deletions.
175 changes: 175 additions & 0 deletions ShellyPlug/ShellyPlug.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php namespace App\SupportedApps\ShellyPlug;

class ShellyPlug extends \App\SupportedApps implements \App\EnhancedApps {

public $config;

function __construct() {
}

public static function getAvailableStats()
{
return [
"cloud" => "Cloud",
"mqtt" => "MQTT",
"ws" => "Websocket",
"sysUptime" => "Uptime",
"state" => "State",
"power" => "Watts",
"tempC" => "Temperature in °C",
"tempF" => "Temperature in °F",
];
}

private static function toTime($timestamp)
{
$hours = floor($timestamp / 3600);
$minutes = floor($timestamp % 3600 / 60);
$seconds = $timestamp % 60;

$hourDuration = sprintf('%02dh', $hours);
$minDuration = sprintf('%02dm', $minutes);
$secDuration = sprintf('%02ds', $seconds);
$HourMinSec = $hourDuration.$minDuration.$secDuration;

if($hourDuration > 0){
$hourDuration = $hourDuration;
} else {
$hourDuration = '00h';
}

if($minDuration > 0){
$minDuration = $minDuration;
} else {
$minDuration = '00m';
}

if($secDuration > 0){
$secDuration = $secDuration;
} else {
$secDuration = '00s';
}

$HourMinSec = $hourDuration.$minDuration.$secDuration;

return $HourMinSec;
}

private static function formatValueUsingStat($stat, $value)
{
if (!isset($value)) {
return "N/A";
}

switch ($stat) {
case "cloud":
case "mqtt":
case "ws":
return (bool)$value ? "Connected" : "Disconnected";
case "sysUptime":
return self::toTime((int)$value);
case "state":
return (bool)$value ? "On" : "Off";
case "power":
return "{$value} W";
case "tempC":
return "{$value} °C";
case "tempF":
return "{$value} °F";
default:
return "{$value}";
}
}

public function test()
{
$test = parent::appTest(
$this->url("Shelly.GetStatus")
);
echo $test->status;
}

public function livestats()
{
$status = 'inactive';
$res = parent::execute($this->url('Shelly.GetStatus'));
$details = json_decode($res->getBody());
$res = parent::execute($this->url('Switch.GetStatus?id=0'));
$switch = json_decode($res->getBody());

$data = ["visiblestats" => []];
if ($details) {
foreach ($this->config->availablestats as $stat) {
if (!isset(self::getAvailableStats()[$stat])) {
continue;
}

$newstat = new \stdClass();

switch ($stat) {
case "cloud":
$newstat->title = self::getAvailableStats()[$stat];
$newstat->value = self::formatValueUsingStat(
$stat,
$details->cloud->connected
);
break;
case "mqtt":
$newstat->title = self::getAvailableStats()[$stat];
$newstat->value = self::formatValueUsingStat(
$stat,
$details->mqtt->connected
);
break;
case "ws":
$newstat->title = self::getAvailableStats()[$stat];
$newstat->value = self::formatValueUsingStat(
$stat,
$details->ws->connected
);
break;
case "sysUptime":
$newstat->title = self::getAvailableStats()[$stat];
$newstat->value = self::formatValueUsingStat(
$stat,
$details->sys->uptime
);
break;
case "state":
$newstat->value = self::formatValueUsingStat(
$stat,
$switch->output
);
break;
case "power":
$newstat->value = self::formatValueUsingStat(
$stat,
$switch->apower
);
break;
case "tempC":
$newstat->value = self::formatValueUsingStat(
$stat,
$switch->temperature->tC
);
break;
case "tempF":
$newstat->value = self::formatValueUsingStat(
$stat,
$switch->temperature->tF
);
break;
}
$data["visiblestats"][] = $newstat;
}
}

return parent::getLiveStats($status, $data);
}

public function url($endpoint)
{
$api_url = parent::normaliseurl($this->config->url)."rpc/".$endpoint;
return $api_url;
}
}
10 changes: 10 additions & 0 deletions ShellyPlug/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"appid": "304c38e1914566a45eb705ba7315a638d25b44ce",
"name": "Shelly Plug",
"website": "https://www.shelly.com/",
"license": "MIT License",
"description": "Shelly offers easy-to-use products for smart home enthusiasts and professionals. The wide product range delivers complete home automation experience and innovative technology at reasonable prices and with attention to the smallest details.\r\n\r\nThis application supports Shelly Plugs.",
"enhanced": true,
"tile_background": "dark",
"icon": "shellyplug.png"
}
15 changes: 15 additions & 0 deletions ShellyPlug/config.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<h2>{{ __('app.apps.config') }} ({{ __('app.optional') }}) @include('items.enable')</h2>
<div class="items">
<div class="input">
<label>{{ strtoupper(__('app.url')) }}</label>
{!! Form::text('config[override_url]', null, array('placeholder' => __('app.apps.override'), 'id' => 'override_url', 'class' => 'form-control')) !!}
</div>
<div class="input">
<label>Stats to show</label>
{!! Form::select('config[availablestats][]', App\SupportedApps\ShellyPlug\ShellyPlug::getAvailableStats(), isset($item) ? $item->getConfig()->availablestats ?? null : null, ['multiple' => 'multiple']) !!}
</div>
<div class="input">
<button style="margin-top: 32px;" class="btn test" id="test_config">Test</button>
</div>
</div>

10 changes: 10 additions & 0 deletions ShellyPlug/livestats.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<ul class="livestats">
@foreach ($visiblestats as $stat)
<li>
@if (isset($stat->title))
<span class="title">{!! $stat->title !!}</span>
@endif
<strong>{!! $stat->value !!}</strong>
</li>
@endforeach
</ul>
Binary file added ShellyPlug/shellyplug.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1ca76bb

Please sign in to comment.