mirror of
https://github.com/CyanoFresh/SmartHomePHP.git
synced 2026-02-19 19:01:20 +01:00
RGB Widget frontend
This commit is contained in:
@@ -21,5 +21,6 @@ class MDThemeAsset extends AssetBundle
|
||||
'yii\web\JqueryAsset',
|
||||
'yii\bootstrap\BootstrapPluginAsset',
|
||||
'app\assets\SnackbarjsAsset',
|
||||
'app\assets\SpectrumAsset',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -12,6 +12,15 @@ $params = [
|
||||
'connectionCheckTimeout' => 180,
|
||||
'connectionCheckMaxIteration' => 2,
|
||||
],
|
||||
'items' => [
|
||||
'rgb' => [
|
||||
'fade-time' => 10000,
|
||||
'color-time' => 5000,
|
||||
'red' => 0,
|
||||
'green' => 150,
|
||||
'blue' => 150,
|
||||
],
|
||||
],
|
||||
'telegramBotApiKey' => '',
|
||||
'telegramBotChatId' => '',
|
||||
];
|
||||
|
||||
24
helpers/RGBHelper.php
Normal file
24
helpers/RGBHelper.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace app\helpers;
|
||||
|
||||
class RGBHelper
|
||||
{
|
||||
/**
|
||||
* @param integer $value
|
||||
* @return integer
|
||||
*/
|
||||
public static function from8to10($value)
|
||||
{
|
||||
return $value * 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $value
|
||||
* @return float|integer
|
||||
*/
|
||||
public static function from10to8($value)
|
||||
{
|
||||
return floor($value / 4);
|
||||
}
|
||||
}
|
||||
@@ -44,9 +44,19 @@ class Item extends ActiveRecord
|
||||
const VALUE_ON = 1;
|
||||
const VALUE_OFF = 0;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
const MODE_RAINBOW = 'rainbow';
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
const MODE_BREATH = 'breath';
|
||||
|
||||
const RGB_MODE_STATIC = 'static';
|
||||
const RGB_MODE_WAVE = 'wave';
|
||||
const RGB_MODE_FADE = 'fade';
|
||||
|
||||
/**
|
||||
* Used for WS handler
|
||||
* @var mixed
|
||||
@@ -213,42 +223,28 @@ class Item extends ActiveRecord
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function getModesArray()
|
||||
public static function getRGBModesArray()
|
||||
{
|
||||
return [
|
||||
self::MODE_RAINBOW,
|
||||
self::MODE_BREATH,
|
||||
self::RGB_MODE_STATIC,
|
||||
self::RGB_MODE_WAVE,
|
||||
self::RGB_MODE_FADE,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns normalized default value
|
||||
* @return mixed
|
||||
*/
|
||||
public function getDefaultValue()
|
||||
public function getDefaultNAValue()
|
||||
{
|
||||
if (!is_null($this->default_value)) {
|
||||
return $this->default_value;
|
||||
}
|
||||
|
||||
switch ($this->type) {
|
||||
case Item::TYPE_SWITCH:
|
||||
case Item::TYPE_VARIABLE_BOOLEAN:
|
||||
case Item::TYPE_VARIABLE_BOOLEAN_DOOR:
|
||||
return false;
|
||||
|
||||
case Item::TYPE_VARIABLE_TEMPERATURE:
|
||||
case Item::TYPE_VARIABLE_HUMIDITY:
|
||||
return 0;
|
||||
|
||||
case Item::TYPE_RGB:
|
||||
case self::TYPE_RGB:
|
||||
return [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
'mode' => 'static',
|
||||
'red' => 0,
|
||||
'green' => 0,
|
||||
'blue' => 0,
|
||||
'fade_time' => Yii::$app->params['items']['rgb']['fade-time'],
|
||||
];
|
||||
default:
|
||||
return 'N/A';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ class ItemController extends Controller
|
||||
throw new BadRequestHttpException('This item is not the RGB one');
|
||||
}
|
||||
|
||||
if (!in_array($mode, Item::getModesArray())) {
|
||||
if (!in_array($mode, Item::getRGBModesArray())) {
|
||||
throw new InvalidParamException('Unknown mode');
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace app\servers;
|
||||
|
||||
use app\helpers\IPHelper;
|
||||
use app\helpers\RGBHelper;
|
||||
use app\models\Board;
|
||||
use app\models\Event;
|
||||
use app\models\Setting;
|
||||
@@ -11,15 +12,18 @@ use app\models\Trigger;
|
||||
use app\models\History;
|
||||
use app\models\Item;
|
||||
use app\models\User;
|
||||
use MongoDB\Driver\Exception\AuthenticationException;
|
||||
use Guzzle\Http\QueryString;
|
||||
use Ratchet\ConnectionInterface;
|
||||
use Ratchet\MessageComponentInterface;
|
||||
use Ratchet\WebSocket\Version\RFC6455\Connection;
|
||||
use React\EventLoop\LoopInterface;
|
||||
use React\EventLoop\Timer\TimerInterface;
|
||||
use Yii;
|
||||
use yii\base\InvalidParamException;
|
||||
use yii\base\NotSupportedException;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use yii\helpers\Json;
|
||||
use yii\web\BadRequestHttpException;
|
||||
use yii\web\ForbiddenHttpException;
|
||||
use yii\web\NotFoundHttpException;
|
||||
use yii\web\UnauthorizedHttpException;
|
||||
@@ -40,13 +44,13 @@ class CoreServer implements MessageComponentInterface
|
||||
* All connected users
|
||||
* @var ConnectionInterface[]
|
||||
*/
|
||||
protected $user_clients;
|
||||
protected $userConnections;
|
||||
|
||||
/**
|
||||
* All connected boards
|
||||
* @var ConnectionInterface[]
|
||||
*/
|
||||
protected $board_clients;
|
||||
protected $boardConnections;
|
||||
|
||||
/**
|
||||
* Format like this:
|
||||
@@ -55,19 +59,19 @@ class CoreServer implements MessageComponentInterface
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $item_values;
|
||||
protected $itemValues;
|
||||
|
||||
/**
|
||||
* `item_id` => TimerInterface
|
||||
* @var TimerInterface[]
|
||||
*/
|
||||
protected $connectionCheckTimers;
|
||||
protected $pingTimers;
|
||||
|
||||
/**
|
||||
* `item_id` => iteration count
|
||||
* @var array
|
||||
*/
|
||||
protected $connectionCheckIteration;
|
||||
protected $pingCount;
|
||||
|
||||
/**
|
||||
* @var TimerInterface[]
|
||||
@@ -85,11 +89,11 @@ class CoreServer implements MessageComponentInterface
|
||||
{
|
||||
// Init variables
|
||||
$this->loop = $loop;
|
||||
$this->user_clients = [];
|
||||
$this->board_clients = [];
|
||||
$this->item_values = [];
|
||||
$this->connectionCheckTimers = [];
|
||||
$this->connectionCheckIteration = [];
|
||||
$this->userConnections = [];
|
||||
$this->boardConnections = [];
|
||||
$this->itemValues = [];
|
||||
$this->pingTimers = [];
|
||||
$this->pingCount = [];
|
||||
$this->triggerTimers = [];
|
||||
|
||||
// Database driver hack: Prevent MySQL for disconnecting by timeout
|
||||
@@ -98,168 +102,40 @@ class CoreServer implements MessageComponentInterface
|
||||
Yii::$app->db->createCommand('SHOW TABLES;')->execute();
|
||||
});
|
||||
|
||||
$this->updateItems();
|
||||
|
||||
// Do the startup tasks
|
||||
// $this->updateItems();
|
||||
$this->scheduleTriggers();
|
||||
|
||||
$this->log('Server started');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function onOpen(ConnectionInterface $conn)
|
||||
{
|
||||
$this->log('Managing new connection...');
|
||||
/** @var Connection $conn */
|
||||
|
||||
/** @var QueryString $query */
|
||||
$query = $conn->WebSocket->request->getQuery();
|
||||
|
||||
$type = $query->get('type');
|
||||
|
||||
switch ($type) {
|
||||
case 'user':
|
||||
$this->log('Connection type is User. Authenticating...');
|
||||
|
||||
$userID = $query->get('id');
|
||||
$userAuthToken = $query->get('auth_token');
|
||||
|
||||
if (!$userID or !$userAuthToken) {
|
||||
$this->log("Invalid credentials: '$userID', '$userAuthToken'");
|
||||
|
||||
throw new InvalidParamException("Required fields does not exist");
|
||||
}
|
||||
|
||||
$user = User::findOne([
|
||||
'id' => $userID,
|
||||
]);
|
||||
|
||||
if (!$user) {
|
||||
$this->log("User was not found with id '$userID'");
|
||||
|
||||
throw new NotFoundHttpException("User was not found with id '$userID'");
|
||||
}
|
||||
|
||||
if ($user->getAuthToken() != $userAuthToken) {
|
||||
$this->log("User [$user->id] wrong auth token ($userAuthToken and {$user->getAuthToken()})");
|
||||
|
||||
throw new AuthenticationException("Wrong credentials");
|
||||
}
|
||||
|
||||
// API request
|
||||
$api = false;
|
||||
|
||||
if ($conn->remoteAddress == '127.0.0.1' and $conn->WebSocket->request->getHeader('Origin') == 'origin') {
|
||||
$api = true;
|
||||
}
|
||||
|
||||
// Close previous connection if it is not an API connection
|
||||
if (isset($this->user_clients[$user->id]) and !$api) {
|
||||
$this->user_clients[$user->id]->close();
|
||||
}
|
||||
|
||||
// Regenerate auth key
|
||||
$user->reGenerateAuthToken();
|
||||
|
||||
// Attach to users
|
||||
$conn->User = $user;
|
||||
$conn->api = $api;
|
||||
$this->user_clients[$user->id] = $conn;
|
||||
|
||||
// Prepare Items for User
|
||||
$items = Item::find()
|
||||
->active()
|
||||
->select(['id', 'type', 'room_id', 'board_id', 'default_value'])
|
||||
->asArray()
|
||||
->all();
|
||||
|
||||
for ($i = 0; $i < count($items); $i++) {
|
||||
$items[$i]['value'] = $this->getItemSavedValue($items[$i]['id'], $items[$i]['default_value']);
|
||||
}
|
||||
|
||||
$conn->send(Json::encode([
|
||||
'type' => 'init',
|
||||
'items' => $items,
|
||||
]));
|
||||
|
||||
$this->logUserConnection($user, true);
|
||||
|
||||
return $this->log("Connected user [{$user->id}] {$user->username}");
|
||||
$this->handleUserConnection($conn, $query);
|
||||
break;
|
||||
case 'board':
|
||||
$this->log('Connection type is Board. Authenticating...');
|
||||
|
||||
$boardID = $query->get('id');
|
||||
$boardSecret = $query->get('secret');
|
||||
|
||||
if (!$boardID or !$boardSecret) {
|
||||
$this->log("Wrong login data: '$boardID' and '$boardSecret'");
|
||||
|
||||
throw new UnauthorizedHttpException('Wrong credentials');
|
||||
}
|
||||
|
||||
$board = Board::findOne([
|
||||
'id' => $boardID,
|
||||
'type' => Board::TYPE_WEBSOCKET,
|
||||
'secret' => $boardSecret,
|
||||
]);
|
||||
|
||||
if (!$board) {
|
||||
$this->log("Board [$boardID] not found!");
|
||||
|
||||
throw new NotFoundHttpException("Board with given ID does not exists");
|
||||
}
|
||||
|
||||
if (!$board->remote_connection and !IPHelper::isLocal($conn->remoteAddress)) {
|
||||
$this->log("Remote connection blocked for board [$boardID]; IP: {$conn->remoteAddress}");
|
||||
|
||||
throw new ForbiddenHttpException("Remote connection is not allowed for this Board");
|
||||
}
|
||||
|
||||
// Attach to boards
|
||||
$conn->Board = $board;
|
||||
$this->board_clients[$board->id] = $conn;
|
||||
|
||||
// Reset previous timer and start a new one
|
||||
$this->startConnectionCheckTimer($boardID, true);
|
||||
|
||||
// Set default values to board's items
|
||||
foreach ($board->items as $item) {
|
||||
if ($item->default_value and !is_null($item->default_value)) {
|
||||
switch ($item->type) {
|
||||
case Item::TYPE_SWITCH:
|
||||
$this->sendToBoard($board->id, [
|
||||
'type' => $item->default_value == 1 ? 'turnON' : 'turnOFF',
|
||||
'pin' => $item->pin,
|
||||
]);
|
||||
|
||||
break;
|
||||
case Item::TYPE_RGB:
|
||||
$rgbData = $this->valueToRgbData($item->default_value);
|
||||
|
||||
$red = $rgbData[0];
|
||||
$green = $rgbData[1];
|
||||
$blue = $rgbData[2];
|
||||
$fade = (bool)$rgbData[3];
|
||||
|
||||
$this->sendToBoard($board->id, [
|
||||
'type' => 'rgb',
|
||||
'red' => $red * 4,
|
||||
'green' => $green * 4,
|
||||
'blue' => $blue * 4,
|
||||
'fade' => $fade,
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->triggerBoardConnection($board, true);
|
||||
|
||||
$this->logBoardConnection($board->id, true);
|
||||
|
||||
return $this->log("Connected board [{$board->id}]");
|
||||
$this->handleBoardConnection($conn, $query);
|
||||
break;
|
||||
default:
|
||||
throw new BadRequestHttpException('Unknown device type');
|
||||
}
|
||||
|
||||
return $this->log('Connection has unknown type. Disconnect');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function onMessage(ConnectionInterface $from, $msg)
|
||||
{
|
||||
if (isset($from->User)) {
|
||||
@@ -275,6 +151,9 @@ class CoreServer implements MessageComponentInterface
|
||||
return $this->log("Message: '$msg' from unknown client");
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function onClose(ConnectionInterface $conn)
|
||||
{
|
||||
if (isset($conn->User)) {
|
||||
@@ -284,12 +163,10 @@ class CoreServer implements MessageComponentInterface
|
||||
} elseif (isset($conn->Board)) {
|
||||
$boardId = $conn->Board->id;
|
||||
|
||||
$this->log("Disconnecting Board [{$boardId}]...");
|
||||
|
||||
// Cancel connection check timer
|
||||
$this->stopConnectionCheckTimer($boardId);
|
||||
$this->stopPingTimer($boardId);
|
||||
|
||||
unset($this->board_clients[$boardId]);
|
||||
unset($this->boardConnections[$boardId]);
|
||||
|
||||
$this->triggerBoardConnection($conn->Board, false);
|
||||
|
||||
@@ -299,6 +176,9 @@ class CoreServer implements MessageComponentInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function onError(ConnectionInterface $conn, \Exception $e)
|
||||
{
|
||||
$this->log("Error: {$e->getMessage()} in file {$e->getFile()} at line {$e->getLine()}");
|
||||
@@ -307,6 +187,160 @@ class CoreServer implements MessageComponentInterface
|
||||
$conn->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection $conn
|
||||
* @param QueryString $query
|
||||
* @throws UnauthorizedHttpException
|
||||
*/
|
||||
protected function handleUserConnection($conn, $query)
|
||||
{
|
||||
$userID = $query->get('id');
|
||||
$userAuthToken = $query->get('auth_token');
|
||||
|
||||
$user = User::findOne([
|
||||
'id' => $userID,
|
||||
'auth_token' => $userAuthToken,
|
||||
]);
|
||||
|
||||
if (!$user) {
|
||||
$this->log("Wrong credentials: '$userID', '$userAuthToken''");
|
||||
|
||||
throw new UnauthorizedHttpException("Wrong credentials");
|
||||
}
|
||||
|
||||
// Check if it is an API request
|
||||
$api = $conn->remoteAddress == '127.0.0.1' and $conn->WebSocket->request->getHeader('Origin') == 'origin';
|
||||
|
||||
// Close previous connection if it is not an API connection
|
||||
if (isset($this->userConnections[$user->id]) and !$api) {
|
||||
$this->userConnections[$user->id]->close();
|
||||
}
|
||||
|
||||
// Regenerate auth token
|
||||
$user->reGenerateAuthToken();
|
||||
|
||||
// Attach to users
|
||||
$conn->User = $user;
|
||||
$conn->api = $api;
|
||||
|
||||
$this->userConnections[$user->id] = $conn;
|
||||
|
||||
// Prepare Items for User
|
||||
$itemModels = Item::find()
|
||||
->active()
|
||||
->all();
|
||||
|
||||
$items = [];
|
||||
|
||||
foreach ($itemModels as $itemModel) {
|
||||
$itemData = [];
|
||||
$itemData['id'] = $itemModel->id;
|
||||
$itemData['type'] = $itemModel->type;
|
||||
$itemData['room_id'] = $itemModel->room_id;
|
||||
$itemData['board_id'] = $itemModel->board_id;
|
||||
$itemData['pin'] = $itemModel->pin;
|
||||
$itemData['name'] = $itemModel->name;
|
||||
$itemData['icon'] = $itemModel->icon;
|
||||
$itemData['bg'] = $itemModel->bg;
|
||||
$itemData['class'] = $itemModel->class;
|
||||
$itemData['sort_order'] = $itemModel->sort_order;
|
||||
|
||||
$itemData['value'] = $this->getItemSavedValue($itemModel->id, $itemModel->getDefaultNAValue());
|
||||
|
||||
$items[$itemModel->id] = $itemData;
|
||||
}
|
||||
|
||||
$conn->send(Json::encode([
|
||||
'type' => 'init',
|
||||
'items' => $items,
|
||||
]));
|
||||
|
||||
$this->logUserConnection($user, true);
|
||||
|
||||
$this->log("Connected user [{$user->id}] {$user->username}");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConnectionInterface $conn
|
||||
* @param QueryString $query
|
||||
* @throws ForbiddenHttpException
|
||||
* @throws NotFoundHttpException
|
||||
* @throws UnauthorizedHttpException
|
||||
*/
|
||||
protected function handleBoardConnection(ConnectionInterface $conn, $query)
|
||||
{
|
||||
$boardID = $query->get('id');
|
||||
$boardSecret = $query->get('secret');
|
||||
|
||||
if (!$boardID or !$boardSecret) {
|
||||
$this->log("Wrong board login data: '$boardID' and '$boardSecret'");
|
||||
|
||||
throw new UnauthorizedHttpException('Wrong credentials');
|
||||
}
|
||||
|
||||
$board = Board::findOne([
|
||||
'id' => $boardID,
|
||||
'type' => Board::TYPE_WEBSOCKET,
|
||||
'secret' => $boardSecret,
|
||||
]);
|
||||
|
||||
if (!$board) {
|
||||
$this->log("Board [$boardID] not found!");
|
||||
|
||||
throw new NotFoundHttpException("Board with given ID does not exists");
|
||||
}
|
||||
|
||||
if (!$board->remote_connection and !IPHelper::isLocal($conn->remoteAddress)) {
|
||||
$this->log("Remote connection blocked for board [$boardID]; IP: {$conn->remoteAddress}");
|
||||
|
||||
throw new ForbiddenHttpException("Remote connection is not allowed for this Board");
|
||||
}
|
||||
|
||||
// Attach to boards
|
||||
$conn->Board = $board;
|
||||
$this->boardConnections[$board->id] = $conn;
|
||||
|
||||
// Reset previous timer and start a new one
|
||||
$this->startPingTimer($boardID, true);
|
||||
|
||||
// Set default values to board's items
|
||||
// foreach ($board->items as $item) {
|
||||
// if ($item->default_value and !is_null($item->default_value)) {
|
||||
// switch ($item->type) {
|
||||
// case Item::TYPE_SWITCH:
|
||||
// $this->sendToBoard($board->id, [
|
||||
// 'type' => $item->default_value == 1 ? 'turnON' : 'turnOFF',
|
||||
// 'pin' => $item->pin,
|
||||
// ]);
|
||||
//
|
||||
// break;
|
||||
// case Item::TYPE_RGB:
|
||||
// $rgbData = $this->valueToRgbData($item->default_value);
|
||||
//
|
||||
// $red = $rgbData[0];
|
||||
// $green = $rgbData[1];
|
||||
// $blue = $rgbData[2];
|
||||
// $fade = (bool)$rgbData[3];
|
||||
//
|
||||
// $this->sendToBoard($board->id, [
|
||||
// 'type' => 'rgb',
|
||||
// 'red' => $red * 4,
|
||||
// 'green' => $green * 4,
|
||||
// 'blue' => $blue * 4,
|
||||
// 'fade' => $fade,
|
||||
// ]);
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
$this->triggerBoardConnection($board, true);
|
||||
$this->logBoardConnection($board->id, true);
|
||||
|
||||
$this->log("Connected board [{$board->id}]");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $from
|
||||
* @param $msg
|
||||
@@ -328,8 +362,6 @@ class CoreServer implements MessageComponentInterface
|
||||
return $this->handleTurnOff($from, $user, $data);
|
||||
case 'rgb':
|
||||
return $this->handleRgb($from, $user, $data);
|
||||
case 'rgbMode':
|
||||
return $this->handleRgbMode($from, $user, $data);
|
||||
case 'schedule-triggers':
|
||||
return $this->scheduleTriggers();
|
||||
case 'update-items':
|
||||
@@ -345,6 +377,7 @@ class CoreServer implements MessageComponentInterface
|
||||
* @param $from
|
||||
* @param $msg
|
||||
* @return bool
|
||||
* @throws NotFoundHttpException
|
||||
*/
|
||||
public function handleBoardMessage($from, $msg)
|
||||
{
|
||||
@@ -352,8 +385,8 @@ class CoreServer implements MessageComponentInterface
|
||||
$board = $from->Board;
|
||||
$data = Json::decode($msg);
|
||||
|
||||
// Board responds: restart connection check timer
|
||||
$this->startConnectionCheckTimer($board->id);
|
||||
// Restart ping timer
|
||||
$this->startPingTimer($board->id);
|
||||
|
||||
switch ($data['type']) {
|
||||
case 'value':
|
||||
@@ -385,42 +418,67 @@ class CoreServer implements MessageComponentInterface
|
||||
$this->logItemValue($item, $value);
|
||||
|
||||
break;
|
||||
case 'rgbMode':
|
||||
/**
|
||||
* Message structure:
|
||||
* {"start":true,"type":"rgbMode","mode":"rainbow","pin":1}
|
||||
*/
|
||||
$value = $data['mode'];
|
||||
$pin = (integer)$data['pin'];
|
||||
$start = (bool)$data['start'];
|
||||
case 'rgb':
|
||||
$itemId = (integer)$data['item_id'];
|
||||
$mode = $data['mode'];
|
||||
$fadeTime = (int)$data['fade_time'];
|
||||
|
||||
$item = Item::findOne([
|
||||
'id' => $itemId,
|
||||
'board_id' => $board->id,
|
||||
'pin' => $pin,
|
||||
]);
|
||||
|
||||
if (!$item) {
|
||||
return $this->log('Trying to use unknown item');
|
||||
$this->log("Board [{$board->id}] tried to use unknown item");
|
||||
throw new NotFoundHttpException('Item does not exist');
|
||||
}
|
||||
|
||||
if ($start) {
|
||||
$value = $this->saveItemValue($item->id, $value, $item->type, false);
|
||||
} else {
|
||||
$value = $this->saveItemValue($item->id, $item->getDefaultValue(), $item->type);
|
||||
if (!in_array($mode, Item::getRGBModesArray())) {
|
||||
$this->log("Board [{$board->id}] tried to use unknown RGB mode");
|
||||
throw new InvalidParamException('Unknown RGB mode');
|
||||
}
|
||||
|
||||
// TODO: trigger
|
||||
if ($fadeTime < 0) {
|
||||
$fadeTime = 0;
|
||||
}
|
||||
|
||||
$this->sendUsers([
|
||||
'type' => 'value',
|
||||
$commonParameters = [
|
||||
'type' => 'rgb',
|
||||
'item_id' => $item->id,
|
||||
'item_type' => $item->type,
|
||||
'value' => $value,
|
||||
'start' => $start,
|
||||
]);
|
||||
'mode' => $mode,
|
||||
'fade_time' => $fadeTime,
|
||||
];
|
||||
|
||||
// Save to history
|
||||
$this->logItemValue($item, $start ? 'start:' : '' . $value);
|
||||
$modeParameters = [];
|
||||
|
||||
if ($mode === Item::RGB_MODE_STATIC or $mode === Item::RGB_MODE_FADE) {
|
||||
// Fill saved values if not provided
|
||||
$red = isset($data['red']) ? $data['red'] : Yii::$app->params['items']['rgb']['red'];
|
||||
$green = isset($data['green']) ? $data['green'] : Yii::$app->params['items']['rgb']['green'];
|
||||
$blue = isset($data['blue']) ? $data['blue'] : Yii::$app->params['items']['rgb']['blue'];
|
||||
|
||||
// Convert color from 1023 to 255
|
||||
$red = RGBHelper::from10to8($red);
|
||||
$green = RGBHelper::from10to8($green);
|
||||
$blue = RGBHelper::from10to8($blue);
|
||||
|
||||
$modeParameters['red'] = $red;
|
||||
$modeParameters['green'] = $green;
|
||||
$modeParameters['blue'] = $blue;
|
||||
}
|
||||
|
||||
if ($mode === Item::RGB_MODE_WAVE or $mode === Item::RGB_MODE_FADE) {
|
||||
$colorTime = isset($data['color_time']) ? $data['color_time'] : Yii::$app->params['items']['rgb']['color-time'];
|
||||
|
||||
$modeParameters['color_time'] = $colorTime;
|
||||
}
|
||||
|
||||
$parameters = ArrayHelper::merge($commonParameters, $modeParameters);
|
||||
|
||||
$this->sendUsers($parameters);
|
||||
|
||||
$this->logItemValue($item, serialize($parameters));
|
||||
$this->saveItemValue($item->id, $parameters, $item->type);
|
||||
|
||||
break;
|
||||
case 'values':
|
||||
@@ -600,108 +658,66 @@ class CoreServer implements MessageComponentInterface
|
||||
]);
|
||||
}
|
||||
|
||||
$red = $data['red'];
|
||||
$green = $data['green'];
|
||||
$blue = $data['blue'];
|
||||
|
||||
if ($red > 255) {
|
||||
$red = 255;
|
||||
}
|
||||
|
||||
if ($green > 255) {
|
||||
$green = 255;
|
||||
}
|
||||
|
||||
if ($blue > 255) {
|
||||
$blue = 255;
|
||||
}
|
||||
|
||||
$board = $item->board;
|
||||
|
||||
switch ($board->type) {
|
||||
case Board::TYPE_AREST:
|
||||
throw new NotSupportedException();
|
||||
|
||||
case Board::TYPE_WEBSOCKET:
|
||||
if (!$this->isBoardConnected($board->id)) {
|
||||
return $from->send(Json::encode([
|
||||
'type' => 'error',
|
||||
'message' => 'Устройство не подключено',
|
||||
]));
|
||||
}
|
||||
|
||||
$fade = isset($data['fade']) ? (bool)$data['fade'] : false;
|
||||
|
||||
$this->sendToBoard($board->id, [
|
||||
'type' => 'rgb',
|
||||
'red' => $red * 4,
|
||||
'green' => $green * 4,
|
||||
'blue' => $blue * 4,
|
||||
'fade' => $fade,
|
||||
]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// $rgbArray = [
|
||||
// $red,
|
||||
// $green,
|
||||
// $blue
|
||||
// ];
|
||||
|
||||
// $this->item_values[$item->id]['value'] = $rgbArray;
|
||||
|
||||
$history = new History();
|
||||
$history->type = History::TYPE_USER_ACTION;
|
||||
$history->user_id = $user->id;
|
||||
$history->item_id = $item->id;
|
||||
$history->commited_at = time();
|
||||
$history->value = $red . ',' . $green . ',' . $blue;
|
||||
|
||||
if (!$history->save()) {
|
||||
$this->log("Cannot log: ");
|
||||
var_dump($history->errors);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ConnectionInterface $from
|
||||
* @param User $user
|
||||
* @param array $data
|
||||
* @return bool|mixed
|
||||
* @throws NotSupportedException
|
||||
*/
|
||||
protected function handleRgbMode($from, $user, $data)
|
||||
{
|
||||
$item_id = (int)$data['item_id'];
|
||||
$item = Item::findOne($item_id);
|
||||
|
||||
if (!$item) {
|
||||
return $from->send(Json::encode([
|
||||
'type' => 'error',
|
||||
'message' => 'Такое устройство не существует',
|
||||
]));
|
||||
}
|
||||
|
||||
if ($item->type !== Item::TYPE_RGB) {
|
||||
return $from->send(Json::encode([
|
||||
'type' => 'error',
|
||||
'message' => 'Данный тип устройства не является RGB',
|
||||
]));
|
||||
}
|
||||
|
||||
$mode = $data['mode'];
|
||||
$start = (bool)$data['start'];
|
||||
$fadeTime = isset($data['fade_time']) ? $data['fade_time'] : Yii::$app->params['items']['rgb']['fade-time'];
|
||||
|
||||
if (!in_array($mode, Item::getModesArray())) {
|
||||
return $from->send(Json::encode([
|
||||
'type' => 'error',
|
||||
'message' => 'Неизвестный режим',
|
||||
]));
|
||||
if (!in_array($mode, Item::getRGBModesArray())) {
|
||||
throw new InvalidParamException('Unknown RGB mode');
|
||||
}
|
||||
|
||||
if ($fadeTime < 0) {
|
||||
$fadeTime = 0;
|
||||
}
|
||||
|
||||
$commonParameters = [
|
||||
'type' => 'rgb',
|
||||
'item_id' => $item->id,
|
||||
'mode' => $mode,
|
||||
'fade_time' => $fadeTime,
|
||||
];
|
||||
|
||||
$modeParameters = [];
|
||||
|
||||
if ($mode === Item::RGB_MODE_STATIC or $mode === Item::RGB_MODE_FADE) {
|
||||
// Fill saved values if not provided
|
||||
$red = isset($data['red']) ? $data['red'] : Yii::$app->params['items']['rgb']['red'];
|
||||
$green = isset($data['green']) ? $data['green'] : Yii::$app->params['items']['rgb']['green'];
|
||||
$blue = isset($data['blue']) ? $data['blue'] : Yii::$app->params['items']['rgb']['blue'];
|
||||
|
||||
// Convert color from 255 to 1023
|
||||
if ($red > 255) {
|
||||
$red = 255;
|
||||
}
|
||||
|
||||
if ($green > 255) {
|
||||
$green = 255;
|
||||
}
|
||||
|
||||
if ($blue > 255) {
|
||||
$blue = 255;
|
||||
}
|
||||
|
||||
$red = RGBHelper::from8to10($red);
|
||||
$green = RGBHelper::from8to10($green);
|
||||
$blue = RGBHelper::from8to10($blue);
|
||||
|
||||
$modeParameters['red'] = $red;
|
||||
$modeParameters['green'] = $green;
|
||||
$modeParameters['blue'] = $blue;
|
||||
}
|
||||
|
||||
if ($mode === Item::RGB_MODE_WAVE or $mode === Item::RGB_MODE_FADE) {
|
||||
$colorTime = isset($data['color_time']) ? $data['color_time'] : Yii::$app->params['items']['rgb']['color-time'];
|
||||
|
||||
if ($colorTime < 0) {
|
||||
$colorTime = 0;
|
||||
}
|
||||
|
||||
$modeParameters['color_time'] = $colorTime;
|
||||
}
|
||||
|
||||
$parameters = ArrayHelper::merge($commonParameters, $modeParameters);
|
||||
|
||||
$board = $item->board;
|
||||
|
||||
switch ($board->type) {
|
||||
@@ -716,11 +732,7 @@ class CoreServer implements MessageComponentInterface
|
||||
]));
|
||||
}
|
||||
|
||||
$this->sendToBoard($board->id, [
|
||||
'type' => 'rgbMode',
|
||||
'mode' => $mode,
|
||||
'action' => $start ? 'start' : 'stop',
|
||||
]);
|
||||
$this->sendToBoard($board->id, $parameters);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -730,10 +742,10 @@ class CoreServer implements MessageComponentInterface
|
||||
$history->user_id = $user->id;
|
||||
$history->item_id = $item->id;
|
||||
$history->commited_at = time();
|
||||
$history->value = $mode . ', ' . $start ? 'start' : 'stop';
|
||||
$history->value = serialize($parameters);
|
||||
|
||||
if (!$history->save()) {
|
||||
$this->log("Cannot log: ");
|
||||
$this->log("Cannot log:");
|
||||
var_dump($history->errors);
|
||||
}
|
||||
|
||||
@@ -792,7 +804,7 @@ class CoreServer implements MessageComponentInterface
|
||||
{
|
||||
$msg = Json::encode($data);
|
||||
|
||||
foreach ($this->user_clients as $client) {
|
||||
foreach ($this->userConnections as $client) {
|
||||
$client->send($msg);
|
||||
}
|
||||
}
|
||||
@@ -802,24 +814,21 @@ class CoreServer implements MessageComponentInterface
|
||||
*
|
||||
* @param integer $board_id
|
||||
* @param array $data
|
||||
* @return bool|ConnectionInterface
|
||||
*/
|
||||
protected function sendToBoard($board_id, $data)
|
||||
{
|
||||
if (isset($this->board_clients[$board_id])) {
|
||||
if (isset($this->boardConnections[$board_id])) {
|
||||
/** @var ConnectionInterface $client */
|
||||
$client = $this->board_clients[$board_id];
|
||||
$client = $this->boardConnections[$board_id];
|
||||
|
||||
$msg = Json::encode($data);
|
||||
|
||||
$this->log("Sending to board [$board_id]: $msg");
|
||||
|
||||
return $client->send($msg);
|
||||
$client->send($msg);
|
||||
} else {
|
||||
$this->log("Cannot send to board [$board_id]: not connected");
|
||||
}
|
||||
|
||||
$this->log("Cannot send to board [$board_id]: not connected");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -852,7 +861,7 @@ class CoreServer implements MessageComponentInterface
|
||||
*/
|
||||
protected function isBoardConnected($boardID)
|
||||
{
|
||||
return isset($this->board_clients[$boardID]);
|
||||
return isset($this->boardConnections[$boardID]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -973,7 +982,7 @@ class CoreServer implements MessageComponentInterface
|
||||
$this->log("Connection check for Board [$boardID]...");
|
||||
|
||||
// Check if it is already disconnected
|
||||
if (!isset($this->board_clients[$boardID])) {
|
||||
if (!isset($this->boardConnections[$boardID])) {
|
||||
$this->logBoardConnection($boardID, false);
|
||||
|
||||
$this->log("Board [$boardID] has already been disconnected");
|
||||
@@ -981,18 +990,18 @@ class CoreServer implements MessageComponentInterface
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->connectionCheckIteration[$boardID])) {
|
||||
if ($this->connectionCheckIteration[$boardID] >= Yii::$app->params['server']['connectionCheckMaxIteration']) {
|
||||
if (isset($this->pingCount[$boardID])) {
|
||||
if ($this->pingCount[$boardID] >= Yii::$app->params['server']['connectionCheckMaxIteration']) {
|
||||
$this->log("Maximum ignored ping commands reached. Disconnecting...");
|
||||
|
||||
$this->board_clients[$boardID]->close();
|
||||
$this->boardConnections[$boardID]->close();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->connectionCheckIteration[$boardID]++;
|
||||
$this->pingCount[$boardID]++;
|
||||
} else {
|
||||
$this->connectionCheckIteration[$boardID] = 1;
|
||||
$this->pingCount[$boardID] = 1;
|
||||
}
|
||||
|
||||
$this->sendToBoard($boardID, [
|
||||
@@ -1356,30 +1365,35 @@ class CoreServer implements MessageComponentInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if item value is stored and if so returns it.
|
||||
* If value is missing - returns default from parameter
|
||||
*
|
||||
* @param int $item_id
|
||||
* @param mixed $defaultValue
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getItemSavedValue($item_id, $defaultValue = false)
|
||||
protected function getItemSavedValue($item_id, $defaultValue = null)
|
||||
{
|
||||
if ($this->hasItemSavedValue($item_id)) {
|
||||
return $this->item_values[$item_id];
|
||||
return $this->itemValues[$item_id];
|
||||
}
|
||||
|
||||
return $defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if item value is stored.
|
||||
*
|
||||
* @param int $item_id
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasItemSavedValue($item_id)
|
||||
{
|
||||
return isset($this->item_values[$item_id]);
|
||||
return isset($this->itemValues[$item_id]) and $this->itemValues[$item_id] !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves to value array and returns it. Normalization is on by default
|
||||
* Saves to value array and returns it. Normalization is enabled by default
|
||||
*
|
||||
* @param int $item_id
|
||||
* @param mixed $value
|
||||
@@ -1393,7 +1407,7 @@ class CoreServer implements MessageComponentInterface
|
||||
$value = $this->normalizeItemValue($value, $item_type);
|
||||
}
|
||||
|
||||
$this->item_values[$item_id] = $value;
|
||||
$this->itemValues[$item_id] = $value;
|
||||
|
||||
return $value;
|
||||
}
|
||||
@@ -1414,9 +1428,6 @@ class CoreServer implements MessageComponentInterface
|
||||
case Item::TYPE_VARIABLE_TEMPERATURE:
|
||||
case Item::TYPE_VARIABLE_HUMIDITY:
|
||||
return (int)$value;
|
||||
|
||||
case Item::TYPE_RGB:
|
||||
return $this->valueToRgb($value);
|
||||
}
|
||||
|
||||
return $value;
|
||||
@@ -1430,14 +1441,14 @@ class CoreServer implements MessageComponentInterface
|
||||
* @param int $boardID
|
||||
* @param bool $stopPrevious
|
||||
*/
|
||||
protected function startConnectionCheckTimer($boardID, $stopPrevious = true)
|
||||
protected function startPingTimer($boardID, $stopPrevious = true)
|
||||
{
|
||||
if ($stopPrevious) {
|
||||
$this->stopConnectionCheckTimer($boardID);
|
||||
$this->stopPingTimer($boardID);
|
||||
}
|
||||
|
||||
// Start connection checks
|
||||
$this->connectionCheckTimers[$boardID] = $this->loop->addPeriodicTimer(
|
||||
$this->pingTimers[$boardID] = $this->loop->addPeriodicTimer(
|
||||
Yii::$app->params['server']['connectionCheckTimeout'],
|
||||
function () use ($boardID) {
|
||||
$this->doConnectionCheckTimer($boardID);
|
||||
@@ -1451,18 +1462,18 @@ class CoreServer implements MessageComponentInterface
|
||||
* @param int $boardID
|
||||
* @param bool $resetCount
|
||||
*/
|
||||
protected function stopConnectionCheckTimer($boardID, $resetCount = true)
|
||||
protected function stopPingTimer($boardID, $resetCount = true)
|
||||
{
|
||||
if (isset($this->connectionCheckTimers[$boardID])) {
|
||||
if ($this->connectionCheckTimers[$boardID] instanceof TimerInterface) {
|
||||
$this->connectionCheckTimers[$boardID]->cancel();
|
||||
if (isset($this->pingTimers[$boardID])) {
|
||||
if ($this->pingTimers[$boardID] instanceof TimerInterface) {
|
||||
$this->pingTimers[$boardID]->cancel();
|
||||
}
|
||||
|
||||
unset($this->connectionCheckTimers[$boardID]);
|
||||
unset($this->pingTimers[$boardID]);
|
||||
}
|
||||
|
||||
if ($resetCount and isset($this->connectionCheckIteration[$boardID])) {
|
||||
unset($this->connectionCheckIteration[$boardID]);
|
||||
if ($resetCount and isset($this->pingCount[$boardID])) {
|
||||
unset($this->pingCount[$boardID]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use rmrevin\yii\fontawesome\FA;
|
||||
|
||||
?>
|
||||
|
||||
<div class="col-lg-2 col-md-4 col-sm-6">
|
||||
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||
<div class="panel-item panel-item-rgb withripple <?= $item->class ?>" data-item-id="<?= $item->id ?>">
|
||||
<div class="panel-item-rgb-icon">
|
||||
<?= FA::i($item->icon) ?>
|
||||
|
||||
@@ -14,6 +14,6 @@ use rmrevin\yii\fontawesome\FA;
|
||||
<div class="item-variable-icon">
|
||||
<?= FA::i($item->icon) ?>
|
||||
</div>
|
||||
<div class="item-variable-value item-value"><?= $item->getDefaultValue() ?></div>
|
||||
<div class="item-variable-value item-value"><?= $item->getDefaultNAValue() ?></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -72,27 +72,89 @@ $this->title = 'Панель Управления';
|
||||
</main>
|
||||
|
||||
<script id="rgb-item-widget-popover-content" type="text/x-handlebars-template">
|
||||
<ul class="nav nav-tabs nav-justified">
|
||||
<li class="active">
|
||||
<a href="#rgb-color" data-toggle="tab" aria-expanded="true">
|
||||
Цвет
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#rgb-mode" data-toggle="tab" aria-expanded="false">
|
||||
Режим
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade in active" id="rgb-color">
|
||||
<input type="text"
|
||||
id="colorpicker-{{item_id}}"
|
||||
class="rgb-colorpicker"
|
||||
data-item-id="{{item_id}}">
|
||||
</div>
|
||||
<div class="tab-pane fade" id="rgb-mode">
|
||||
<p>Выберите режим</p>
|
||||
<div class="rgb-widget-popover-content" data-item-id="{{item_id}}">
|
||||
<ul class="nav nav-tabs nav-justified">
|
||||
<li class="active">
|
||||
<a href="#rgb-widget-static" class="rgb-widget-mode rgb-widget-mode-static" data-toggle="tab"
|
||||
aria-expanded="true">
|
||||
Static
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#rgb-widget-wave" class="rgb-widget-mode rgb-widget-mode-wave" data-toggle="tab"
|
||||
aria-expanded="false">
|
||||
Wave
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#rgb-widget-fade" class="rgb-widget-mode rgb-widget-mode-fade" data-toggle="tab"
|
||||
aria-expanded="false">
|
||||
Fade
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade in active" id="rgb-widget-static">
|
||||
<form class="rgb-widget-form rgb-widget-form-static">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label for="colorpicker-{{item_id}}" class="hidden">Цвет</label>
|
||||
<input type="text"
|
||||
class="rgb-widget-colorpicker rgb-widget-colorpicker-static"
|
||||
data-item-id="{{item_id}}"
|
||||
id="colorpicker-{{item_id}}">
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="rgb-widget-static-fade-time">Время перехода (мс)</label>
|
||||
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-static-fade-time"
|
||||
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="rgb-widget-wave">
|
||||
<form class="rgb-widget-form rgb-widget-form-wave">
|
||||
<div class="form-group">
|
||||
<label for="rgb-widget-wave-fade-time">Время перехода (мс)</label>
|
||||
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-wave-fade-time"
|
||||
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="rgb-widget-wave-color-time">Время цвета (мс)</label>
|
||||
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-wave-color-time"
|
||||
value="<?= Yii::$app->params['items']['rgb']['color-time'] ?>">
|
||||
</div>
|
||||
<button class="btn btn-primary btn-save-times" data-mode="wave">Применить</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="rgb-widget-fade">
|
||||
<form class="rgb-widget-form rgb-widget-form-fade">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<label for="fade-colorpicker-{{item_id}}" class="hidden">Цвет</label>
|
||||
<input type="text"
|
||||
class="rgb-widget-colorpicker rgb-widget-colorpicker-fade"
|
||||
data-item-id="{{item_id}}"
|
||||
id="fade-colorpicker-{{item_id}}">
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="rgb-widget-fade-fade-time">Время перехода (мс)</label>
|
||||
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-fade-fade-time"
|
||||
value="<?= Yii::$app->params['items']['rgb']['fade-time'] ?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="rgb-widget-fade-color-time">Время цвета (мс)</label>
|
||||
<input type="number" min="0" step="500" class="form-control" id="rgb-widget-fade-color-time"
|
||||
value="<?= Yii::$app->params['items']['rgb']['color-time'] ?>">
|
||||
</div>
|
||||
<button class="btn btn-primary btn-save-times" data-mode="fade">Применить</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -4,6 +4,3 @@
|
||||
|
||||
$this->title = 'Главная';
|
||||
?>
|
||||
<div class="site-index">
|
||||
<h1 class="page-header"><?= $this->title ?></h1>
|
||||
</div>
|
||||
|
||||
@@ -183,7 +183,7 @@ body {
|
||||
display: block;
|
||||
position: relative;
|
||||
height: 1px;
|
||||
width:100%;
|
||||
width: 100%;
|
||||
background: #efefef;
|
||||
margin: 10px 0;
|
||||
}
|
||||
@@ -290,7 +290,7 @@ body {
|
||||
}
|
||||
|
||||
.panel-item.panel-item-rgb {
|
||||
background: #909090;
|
||||
background: #009688;
|
||||
border-radius: 30px;
|
||||
color: #fff;
|
||||
margin: 10px 0;
|
||||
@@ -300,15 +300,12 @@ body {
|
||||
height: 50px;
|
||||
width: 100%;
|
||||
box-shadow: 0 1px 1.5px 0 rgba(0, 0, 0, .12), 0 1px 1px 0 rgba(0, 0, 0, .24);
|
||||
transition: 0.5s;
|
||||
transition: 1s;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.popover {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
width: 300px;
|
||||
/*height: 200px;*/
|
||||
box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12);
|
||||
max-width: none;
|
||||
border-radius: 0;
|
||||
@@ -323,6 +320,35 @@ body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.rgb-widget-form {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sp-container {
|
||||
display: block;
|
||||
border-radius: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sp-picker-container {
|
||||
width: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.sp-picker-container, .sp-palette-container {
|
||||
float: none;
|
||||
padding: 2px 0 0 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 767px) {
|
||||
.popover {
|
||||
width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Snackbar fixes */
|
||||
#snackbar-container {
|
||||
position: fixed;
|
||||
@@ -442,7 +468,7 @@ body.login-body {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.material-table thead a:hover,.material-table thead a:active {
|
||||
.material-table thead a:hover, .material-table thead a:active {
|
||||
color: #373737;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
/* Content loader */
|
||||
#loader {
|
||||
position: relative;
|
||||
|
||||
@@ -5966,28 +5966,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-default:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #444444 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #444444 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-default:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-primary {
|
||||
position: relative;
|
||||
}
|
||||
@@ -6002,28 +5980,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-primary:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-primary:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-success {
|
||||
position: relative;
|
||||
}
|
||||
@@ -6038,28 +5994,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-success:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-success:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-info {
|
||||
position: relative;
|
||||
}
|
||||
@@ -6074,28 +6008,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-info:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-info:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-warning {
|
||||
position: relative;
|
||||
}
|
||||
@@ -6110,28 +6022,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-warning:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-warning:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-danger {
|
||||
position: relative;
|
||||
}
|
||||
@@ -6146,28 +6036,6 @@ button.close {
|
||||
-webkit-box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.btn-danger:after {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-image: -webkit-radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-image: radial-gradient(circle, #ffffff 10%, transparent 10.01%);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1000% 1000%;
|
||||
background-position: 50%;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: background .5s, opacity 1s;
|
||||
}
|
||||
.btn-danger:active:after {
|
||||
background-size: 0% 0%;
|
||||
opacity: .2;
|
||||
transition: 0s;
|
||||
}
|
||||
.btn-link {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
385
web/js/panel.js
385
web/js/panel.js
@@ -41,7 +41,15 @@ function onMessage(e) {
|
||||
switch (data.type) {
|
||||
case 'init':
|
||||
$.each(data.items, function (key, value) {
|
||||
updateItemValue(value.id, value.type, value.value)
|
||||
if (value.type == 30) {
|
||||
updateRGB(value.id, value.value);
|
||||
} else {
|
||||
if (value.value != 'N/A') {
|
||||
saveItemValue(id, value.value);
|
||||
}
|
||||
|
||||
updateItemValue(value.id, value.type, value.value);
|
||||
}
|
||||
});
|
||||
|
||||
afterConnected();
|
||||
@@ -68,13 +76,15 @@ function afterConnected() {
|
||||
});
|
||||
}
|
||||
|
||||
function send(msg) {
|
||||
if (typeof msg != "string") {
|
||||
msg = JSON.stringify(msg);
|
||||
function send(data) {
|
||||
console.log(data);
|
||||
|
||||
if (typeof data != "string") {
|
||||
data = JSON.stringify(data);
|
||||
}
|
||||
|
||||
if (WS && WS.readyState == 1) {
|
||||
WS.send(msg);
|
||||
WS.send(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +92,20 @@ function updateValue(data) {
|
||||
updateItemValue(data.item_id, data.item_type, data.value);
|
||||
}
|
||||
|
||||
function updateRGB(itemId, data) {
|
||||
itemValues[itemId] = data;
|
||||
|
||||
if (data.mode == 'static' || data.mode == 'fade') {
|
||||
$('.panel-item-rgb[data-item-id="' + itemId + '"]').attr('style', 'background: rgb(' + data.red + ',' + data.green + ',' + data.blue + ')');
|
||||
}
|
||||
|
||||
$('#rgb-widget-wave-fade-time').val(data.fade_time);
|
||||
|
||||
if (data.mode == 'fade' || data.mode == 'wave') {
|
||||
$('#rgb-widget-wave-color-time').val(data.color_time);
|
||||
}
|
||||
}
|
||||
|
||||
function itemSwitchOn(itemId) {
|
||||
var $item = $('.panel-item-switch[data-item-id="' + itemId + '"]');
|
||||
$item.removeClass('off');
|
||||
@@ -96,12 +120,22 @@ function itemSetValue(itemId, value) {
|
||||
$('.panel-item-variable[data-item-id="' + itemId + '"] > .item-variable-value').html(value);
|
||||
}
|
||||
|
||||
function saveItemValue(itemId, value) {
|
||||
itemValues[itemId] = value;
|
||||
}
|
||||
|
||||
function getSavedItemValue(itemId) {
|
||||
return itemValues[itemId];
|
||||
}
|
||||
|
||||
function updateItemValue(id, type, value) {
|
||||
type = parseInt(type);
|
||||
|
||||
switch (type) {
|
||||
case 10: // Switch
|
||||
if (Boolean(value)) {
|
||||
value = Boolean(value);
|
||||
|
||||
if (value) {
|
||||
itemSwitchOn(id);
|
||||
} else {
|
||||
itemSwitchOff(id);
|
||||
@@ -118,189 +152,226 @@ function updateItemValue(id, type, value) {
|
||||
itemSetValue(id, value + '%');
|
||||
break;
|
||||
case 25: // Variable boolean
|
||||
value = Boolean(value) ? 'да' : 'нет';
|
||||
if (Boolean(value)) {
|
||||
if (value != 'N/A') {
|
||||
value = 'да';
|
||||
}
|
||||
} else {
|
||||
value = 'нет';
|
||||
}
|
||||
|
||||
itemSetValue(id, value);
|
||||
|
||||
break;
|
||||
case 26: // Variable boolean door
|
||||
if (value) {
|
||||
value = 'открыто';
|
||||
if (value != 'N/A') {
|
||||
value = 'открыто';
|
||||
}
|
||||
} else {
|
||||
value = 'закрыто';
|
||||
}
|
||||
|
||||
itemSetValue(id, value);
|
||||
|
||||
break;
|
||||
case 30: // RGB
|
||||
itemValues[id] = value;
|
||||
// TODO
|
||||
// if (typeof value === 'string') {
|
||||
// $('.item-rgb[data-item-id="' + id + '"]')
|
||||
// .find('.rgb-mode[data-mode="' + value + '"]')
|
||||
// .addClass('active');
|
||||
// } else {
|
||||
// var $colorPicker = $('#colorpicker-' + id);
|
||||
//
|
||||
// $colorPicker.spectrum('set', 'rgb(' + value[0] + ', ' + value[1] + ', ' + value[2] + ')');
|
||||
//
|
||||
// $('.item-rgb .rgb-mode').removeClass('active');
|
||||
// }
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
// Event listeners
|
||||
$('.panel-item-switch').click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var item_id = $(this).data('item-id');
|
||||
var action = $(this).hasClass('off') ? 'turnON' : 'turnOFF';
|
||||
var $this = $(this);
|
||||
|
||||
var item_id = $this.data('item-id');
|
||||
|
||||
send({
|
||||
"type": action,
|
||||
"type": $this.hasClass('off') ? 'turnON' : 'turnOFF',
|
||||
"item_id": item_id
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$('.panel-item-variable').tooltip();
|
||||
|
||||
$('.panel-item-rgb').popover({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
trigger: 'click',
|
||||
content: function () {
|
||||
var source = $("#rgb-item-widget-popover-content").html();
|
||||
var template = Handlebars.compile(source);
|
||||
// RGB Widget
|
||||
$('.panel-item-rgb')
|
||||
.popover({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
trigger: 'click',
|
||||
container: 'body',
|
||||
content: function () {
|
||||
var source = $("#rgb-item-widget-popover-content").html();
|
||||
var template = Handlebars.compile(source);
|
||||
|
||||
return template({
|
||||
item_id: $(this).data('item-id')
|
||||
return template({
|
||||
item_id: $(this).data('item-id')
|
||||
});
|
||||
}
|
||||
})
|
||||
// On popover init
|
||||
.on('inserted.bs.popover', function () {
|
||||
var item_id = $(this).data('item-id');
|
||||
|
||||
// Init colorpicker
|
||||
var $colorPicker = $('body').find('.rgb-widget-colorpicker[data-item-id="' + item_id + '"]').spectrum({
|
||||
flat: true,
|
||||
showInput: false,
|
||||
showButtons: false,
|
||||
preferredFormat: 'rgb'
|
||||
});
|
||||
}
|
||||
}).on('inserted.bs.popover', function (e) {
|
||||
var $colorPicker = $(this).parent().find('input').spectrum({
|
||||
flat: true,
|
||||
showInput: true,
|
||||
showButtons: false,
|
||||
preferredFormat: 'rgb',
|
||||
dragstop: function (color) {
|
||||
console.log($(this));
|
||||
var item_id = $(this).data('item-id');
|
||||
|
||||
var savedItemValue = getSavedItemValue(item_id);
|
||||
|
||||
// Set colorpicker value
|
||||
if (savedItemValue != null) {
|
||||
$colorPicker.spectrum('set', 'rgb(' + savedItemValue['red'] + ',' + savedItemValue['green'] + ',' + savedItemValue['blue'] + ')');
|
||||
}
|
||||
|
||||
// Set mode and variables
|
||||
if (savedItemValue.mode == 'static') {
|
||||
$('.rgb-widget-mode-static').tab('show');
|
||||
} else if (savedItemValue.mode == 'wave') {
|
||||
$('#rgb-widget-wave-color-time').val(savedItemValue.color_time);
|
||||
$('#rgb-widget-fade-color-time').val(savedItemValue.color_time);
|
||||
|
||||
$('.rgb-widget-mode-wave').tab('show');
|
||||
} else if (savedItemValue.mode == 'fade') {
|
||||
$('#rgb-widget-wave-color-time').val(savedItemValue.color_time);
|
||||
$('#rgb-widget-fade-color-time').val(savedItemValue.color_time);
|
||||
|
||||
$('.rgb-widget-mode-fade').tab('show');
|
||||
}
|
||||
|
||||
$('#rgb-widget-static-fade-time').val(savedItemValue.fade_time);
|
||||
$('#rgb-widget-wave-fade-time').val(savedItemValue.fade_time);
|
||||
$('#rgb-widget-fade-fade-time').val(savedItemValue.fade_time);
|
||||
|
||||
// On color select
|
||||
$colorPicker.on("dragstop.spectrum", function (e, color) {
|
||||
var red = Math.round(color._r);
|
||||
var green = Math.round(color._g);
|
||||
var blue = Math.round(color._b);
|
||||
//
|
||||
// var fade = ($('.fade-checkbox[data-item-id="' + item_id + '"]:checked').length > 0);
|
||||
//
|
||||
// send({
|
||||
// 'type': 'rgb',
|
||||
// 'item_id': item_id,
|
||||
// 'fade': fade,
|
||||
// 'red': red,
|
||||
// 'green': green,
|
||||
// 'blue': blue
|
||||
// });
|
||||
$('.panel-item-rgb[data-item-id="' + item_id + '"]').attr('style', 'background: rgb(' + red + ',' + green + ',' + blue + ')');
|
||||
}
|
||||
|
||||
var $this = $(this);
|
||||
var itemId = $this.data('item-id');
|
||||
|
||||
$('.panel-item-rgb[data-item-id="' + itemId + '"]')
|
||||
.attr('style', 'background-color: rgb(' + red + ',' + green + ',' + blue + ')');
|
||||
|
||||
var modeId = $this.parents('.tab-pane').attr('id');
|
||||
|
||||
if (modeId == 'rgb-widget-static') {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"fade_time": parseInt($('#rgb-widget-static-fade-time').val()),
|
||||
"mode": "static",
|
||||
"red": red,
|
||||
"green": green,
|
||||
"blue": blue
|
||||
});
|
||||
} else if (modeId == 'rgb-widget-fade') {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"fade_time": parseInt($('#rgb-widget-fade-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-fade-color-time').val()),
|
||||
"mode": "fade",
|
||||
"red": red,
|
||||
"green": green,
|
||||
"blue": blue
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('.btn-save-times').click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var mode = $(this).data('mode');
|
||||
|
||||
if (mode == 'wave') {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"mode": "wave",
|
||||
"fade_time": parseInt($('#rgb-widget-wave-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-wave-color-time').val())
|
||||
});
|
||||
} else if (mode == 'fade') {
|
||||
var color = $('.rgb-widget-colorpicker-fade').spectrum('get');
|
||||
var red = Math.round(color._r);
|
||||
var green = Math.round(color._g);
|
||||
var blue = Math.round(color._b);
|
||||
|
||||
if (savedItemValue != null) {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"mode": "fade",
|
||||
"fade_time": parseInt($('#rgb-widget-fade-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-fade-color-time').val()),
|
||||
"red": red,
|
||||
"green": green,
|
||||
"blue": blue
|
||||
});
|
||||
} else {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"mode": "fade",
|
||||
"fade_time": parseInt($('#rgb-widget-fade-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-fade-color-time').val())
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('.rgb-widget-popover-content[data-item-id="' + item_id + '"]').on('click', '.rgb-widget-mode', function (e) {
|
||||
var $this = $(this);
|
||||
|
||||
if ($this.attr('aria-expanded') == 'true') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this.hasClass('rgb-widget-mode-static')) {
|
||||
var color = $('.rgb-widget-colorpicker-static').spectrum('get');
|
||||
var red = Math.round(color._r);
|
||||
var green = Math.round(color._g);
|
||||
var blue = Math.round(color._b);
|
||||
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"fade_time": parseInt($('#rgb-widget-static-fade-time').val()),
|
||||
"mode": "static",
|
||||
"red": red,
|
||||
"green": green,
|
||||
"blue": blue
|
||||
});
|
||||
} else if ($this.hasClass('rgb-widget-mode-wave')) {
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"mode": "wave",
|
||||
"fade_time": parseInt($('#rgb-widget-wave-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-wave-color-time').val())
|
||||
});
|
||||
} else if ($this.hasClass('rgb-widget-mode-fade')) {
|
||||
var color = $('.rgb-widget-colorpicker-fade').spectrum('get');
|
||||
var red = Math.round(color._r);
|
||||
var green = Math.round(color._g);
|
||||
var blue = Math.round(color._b);
|
||||
|
||||
send({
|
||||
"type": "rgb",
|
||||
"item_id": item_id,
|
||||
"mode": "fade",
|
||||
"fade_time": parseInt($('#rgb-widget-fade-fade-time').val()),
|
||||
"color_time": parseInt($('#rgb-widget-fade-color-time').val())
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var item_id = $colorPicker.data('item-id');
|
||||
|
||||
if (Boolean(itemValues[item_id]) != false) {
|
||||
$colorPicker.spectrum('set', itemValues[item_id]);
|
||||
}
|
||||
|
||||
$colorPicker.on("dragstop.spectrum", function (e, color) {
|
||||
var red = Math.round(color._r);
|
||||
var green = Math.round(color._g);
|
||||
var blue = Math.round(color._b);
|
||||
|
||||
$('.panel-item-rgb[data-item-id="' + $(this).data('item-id') + '"]').attr('style', 'background-color: rgb(' + red + ',' + green + ',' + blue + ')')
|
||||
});
|
||||
});
|
||||
|
||||
// TODO:
|
||||
// $('.rgb-colorpicker').spectrum({
|
||||
// showInput: true,
|
||||
// showButtons: false,
|
||||
// preferredFormat: 'rgb',
|
||||
// change: function (color) {
|
||||
// var item_id = $(this).data('item-id');
|
||||
// var red = Math.round(color._r);
|
||||
// var green = Math.round(color._g);
|
||||
// var blue = Math.round(color._b);
|
||||
//
|
||||
// var fade = ($('.fade-checkbox[data-item-id="' + item_id + '"]:checked').length > 0);
|
||||
//
|
||||
// send({
|
||||
// 'type': 'rgb',
|
||||
// 'item_id': item_id,
|
||||
// 'fade': fade,
|
||||
// 'red': red,
|
||||
// 'green': green,
|
||||
// 'blue': blue
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
|
||||
// $('.fade-checkbox').each(function () {
|
||||
// var localStorageValue = window.localStorage.getItem('fade-checkbox-' + $(this).data('item-id'));
|
||||
//
|
||||
// console.log(localStorageValue);
|
||||
//
|
||||
// this.checked = localStorageValue != null && localStorageValue != 'false';
|
||||
// });
|
||||
|
||||
// initWebSocket(function () {
|
||||
// $('input[type="checkbox"].item-switch-checkbox').click(function (e) {
|
||||
// e.preventDefault();
|
||||
//
|
||||
// var item_id = $(this).data('item-id');
|
||||
// var action = $(this).prop('checked') ? 'turnON' : 'turnOFF';
|
||||
//
|
||||
// send({
|
||||
// "type": action,
|
||||
// "item_id": item_id
|
||||
// });
|
||||
// });
|
||||
|
||||
// Delegate click on block to checkbox
|
||||
// $('.item-switch .info-box').click(function (e) {
|
||||
// e.preventDefault();
|
||||
//
|
||||
// if ($(e.target).is('.item-switch-checkbox')) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// $(this).find('.item-switch-checkbox').click();
|
||||
// });
|
||||
|
||||
// $('.rgb-mode').click(function (e) {
|
||||
// e.preventDefault();
|
||||
//
|
||||
// var mode = $(this).data('mode');
|
||||
// var start = true;
|
||||
// var item_id = $(this).parents('.item-rgb').data('item-id');
|
||||
//
|
||||
// if ($(this).hasClass('active')) {
|
||||
// start = false
|
||||
// }
|
||||
//
|
||||
// send({
|
||||
// "type": "rgbMode",
|
||||
// "item_id": item_id,
|
||||
// "mode": mode,
|
||||
// "start": start
|
||||
// });
|
||||
// });
|
||||
|
||||
// $('.fade-checkbox').change(function (e) {
|
||||
// window.localStorage.setItem('fade-checkbox-' + $(this).data('item-id'), this.checked);
|
||||
// });
|
||||
// });
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user