diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 0000000..793693f --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,16 @@ +name: Check Style + +on: [push, pull_request] + +jobs: + style: + runs-on: ubuntu-latest + steps: + - name: Checkout module + uses: actions/checkout@master + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + - name: Check style + uses: wilkware/action-ips-style@main \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..ab27262 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule ".style"] + path = .style + url = https://github.com/Wilkware/StylePHP diff --git a/.style b/.style new file mode 160000 index 0000000..fe04d92 --- /dev/null +++ b/.style @@ -0,0 +1 @@ +Subproject commit fe04d922f53d36e19d91a7f8dfe4ca7c66ed62a4 diff --git a/Color Loop/form.json b/Color Loop/form.json new file mode 100644 index 0000000..684acb6 --- /dev/null +++ b/Color Loop/form.json @@ -0,0 +1,196 @@ +{ + "elements": [ + { + "type": "RowLayout", + "items": [ + { + "type": "Image", + "image": "data:image/png;base64,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", + "link": true, + "onClick": "echo 'https://wilkware.de';" + }, + { + "type": "Label", + "label": "\nColor Loop\n ", + "link": false, + "bold": true + } + ] + }, + { + "type": "Label", + "label": "The module offers the possibility to activate an automatic colour gradient or a colour change." + }, + { + "type": "ExpansionPanel", + "caption": "Circuit ...", + "items": [ + { + "type": "SelectVariable", + "name": "StateVariable", + "caption": "Switch variable:", + "validVariableTypes": [ + 0 + ], + "requiredAction": 1, + "width": "450px" + }, + { + "type": "Label", + "label": "\nThe switching variable serves as an indicator for the switching state (on/off) of the entire lighting group (see Devices).", + "italic": true + } + ] + }, + { + "type": "ExpansionPanel", + "caption": "Devices ...", + "items": [ + { + "type": "List", + "name": "ColorVariables", + "caption": "Light group:", + "add": true, + "delete": true, + "changeOrder": true, + "rowCount": 4, + "columns": [ + { + "name": "Variable", + "caption": "Status variable", + "width": "auto", + "add": 0, + "edit": { + "type": "SelectVariable", + "validVariableTypes": [ + 1 + ], + "requiredAction": 1 + } + }, + { + "name": "Color", + "caption": "Starting color", + "width": "150px", + "add": -1, + "edit": { + "type": "SelectColor", + "allowTransparent": true + } + }, + { + "name": "Name", + "caption": "Lamp name", + "width": "200px", + "add": "", + "edit": { + "type": "ValidationTextBox" + } + } + ] + }, + { + "type": "Label", + "label": "(1) Currently only variables with the profile '~HexColor' are supported.", + "italic": true + }, + { + "type": "Label", + "label": "(2) The 'Transparent' color selection causes the currently set color code to be used as the start color for the corresponding illuminant.", + "italic": true + }, + { + "type": "Label", + "label": "(3) The lamp name is only necessary if you also want to change the start color via the webfront.", + "italic": true + } + ] + }, + { + "type": "ExpansionPanel", + "caption": "Advanced settings ...", + "items": [ + { + "type": "CheckBox", + "name": "CheckColor", + "caption": "Create variables for selection of start color per luminaire?" + } + ] + } + ], + "actions": [ + { + "type": "ExpansionPanel", + "caption": "Source code, donation and licence ...", + "items": [ + { + "type": "Label", + "caption": "The software is free of charge for non-commercial use, I would appreciate a donation if you like the module.", + "bold": true + }, + { + "type": "RowLayout", + "items": [ + { + "type": "Image", + "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTk2Ljc1IiBoZWlnaHQ9IjI4IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IkdJVEhVQjogQFdJTEtXQVJFIj48dGl0bGU+R0lUSFVCOiBAV0lMS1dBUkU8L3RpdGxlPjxnIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyI+PHJlY3Qgd2lkdGg9Ijg3LjUiIGhlaWdodD0iMjgiIGZpbGw9IiM1NTUiLz48cmVjdCB4PSI4Ny41IiB3aWR0aD0iMTA5LjI1IiBoZWlnaHQ9IjI4IiBmaWxsPSIjMTgxNzE3Ii8+PC9nPjxnIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJWZXJkYW5hLEdlbmV2YSxEZWphVnUgU2FucyxzYW5zLXNlcmlmIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiBmb250LXNpemU9IjEwMCI+PGltYWdlIHg9IjkiIHk9IjciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCbWFXeHNQU0ozYUdsMFpYTnRiMnRsSWlCeWIyeGxQU0pwYldjaUlIWnBaWGRDYjNnOUlqQWdNQ0F5TkNBeU5DSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklqNDhkR2wwYkdVK1IybDBTSFZpUEM5MGFYUnNaVDQ4Y0dGMGFDQmtQU0pOTVRJZ0xqSTVOMk10Tmk0Mk15QXdMVEV5SURVdU16Y3pMVEV5SURFeUlEQWdOUzR6TURNZ015NDBNemdnT1M0NElEZ3VNakExSURFeExqTTROUzQyTGpFeE15NDRNaTB1TWpVNExqZ3lMUzQxTnpjZ01DMHVNamcxTFM0d01TMHhMakEwTFM0d01UVXRNaTR3TkMwekxqTXpPQzQzTWpRdE5DNHdOREl0TVM0Mk1TMDBMakEwTWkweExqWXhRelF1TkRJeUlERTRMakEzSURNdU5qTXpJREUzTGpjZ015NDJNek1nTVRjdU4yTXRNUzR3T0RjdExqYzBOQzR3T0RRdExqY3lPUzR3T0RRdExqY3lPU0F4TGpJd05TNHdPRFFnTVM0NE16Z2dNUzR5TXpZZ01TNDRNemdnTVM0eU16WWdNUzR3TnlBeExqZ3pOU0F5TGpnd09TQXhMak13TlNBekxqUTVOUzQ1T1RndU1UQTRMUzQzTnpZdU5ERTNMVEV1TXpBMUxqYzJMVEV1TmpBMUxUSXVOalkxTFM0ekxUVXVORFkyTFRFdU16TXlMVFV1TkRZMkxUVXVPVE1nTUMweExqTXhMalEyTlMweUxqTTRJREV1TWpNMUxUTXVNakl0TGpFek5TMHVNekF6TFM0MU5DMHhMalV5TXk0eE1EVXRNeTR4TnpZZ01DQXdJREV1TURBMUxTNHpNaklnTXk0eklERXVNak11T1RZdExqSTJOeUF4TGprNExTNHpPVGtnTXkwdU5EQTFJREV1TURJdU1EQTJJREl1TURRdU1UTTRJRE1nTGpRd05TQXlMakk0TFRFdU5UVXlJRE11TWpnMUxURXVNak1nTXk0eU9EVXRNUzR5TXk0Mk5EVWdNUzQyTlRNdU1qUWdNaTQ0TnpNdU1USWdNeTR4TnpZdU56WTFMamcwSURFdU1qTWdNUzQ1TVNBeExqSXpJRE11TWpJZ01DQTBMall4TFRJdU9EQTFJRFV1TmpJMUxUVXVORGMxSURVdU9USXVOREl1TXpZdU9ERWdNUzR3T1RZdU9ERWdNaTR5TWlBd0lERXVOakEyTFM0d01UVWdNaTQ0T1RZdExqQXhOU0F6TGpJNE5pQXdJQzR6TVRVdU1qRXVOamt1T0RJMUxqVTNRekl3TGpVMk5TQXlNaTR3T1RJZ01qUWdNVGN1TlRreUlESTBJREV5TGpJNU4yTXdMVFl1TmpJM0xUVXVNemN6TFRFeUxURXlMVEV5SWk4K1BDOXpkbWMrIi8+PHRleHQgdHJhbnNmb3JtPSJzY2FsZSguMSkiIHg9IjUyMi41IiB5PSIxNzUiIHRleHRMZW5ndGg9IjQ2NSIgZmlsbD0iI2ZmZiI+R0lUSFVCPC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSIxNDIxLjI1IiB5PSIxNzUiIHRleHRMZW5ndGg9Ijg1Mi41IiBmaWxsPSIjZmZmIiBmb250LXdlaWdodD0iYm9sZCI+QFdJTEtXQVJFPC90ZXh0PjwvZz48L3N2Zz4=", + "onClick": "echo 'https://wilkware.github.io/';" + }, + { + "type": "Image", + "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTcxLjI1IiBoZWlnaHQ9IjI4IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IlBBWVBBTDogU1BFTkRFTiI+PHRpdGxlPlBBWVBBTDogU1BFTkRFTjwvdGl0bGU+PGcgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj48cmVjdCB3aWR0aD0iODUuNSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzU1NSIvPjxyZWN0IHg9Ijg1LjUiIHdpZHRoPSI4NS43NSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzAwNDU3YyIvPjwvZz48ZyBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0iVmVyZGFuYSxHZW5ldmEsRGVqYVZ1IFNhbnMsc2Fucy1zZXJpZiIgdGV4dC1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiIgZm9udC1zaXplPSIxMDAiPjxpbWFnZSB4PSI5IiB5PSI3IiB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHhsaW5rOmhyZWY9ImRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsUEhOMlp5QjJhV1YzUW05NFBTSXdJREFnTWpRZ01qUWlJSGh0Ykc1elBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHlNREF3TDNOMlp5SStQSEJoZEdnZ1pEMGlUVEU1TGpjeE5TQTJMakV6TTJNdU1qUTVMVEV1T0RZMklEQXRNeTR4TVMwdU9UazVMVFF1TWpZMlF6RTNMall6TkM0Mk1qSWdNVFV1TnpJeElEQWdNVE11TXpBM0lEQklOaTR5TXpWakxTNDBNVGdnTUMwdU9URTJMalEwTkMweElDNDRPRGxNTWk0ek1qTWdNakF1TmpJeVl6QWdMak0xTmk0eU5TNDRMalkyTlM0NGFEUXVNekk0YkMwdU1qVWdNUzQ1TlRaakxTNHdPRFF1TXpVMUxqRTJOaTQyTWpJdU5EazRMall5TW1nekxqWTJNMk11TkRFM0lEQWdMamd6TWkwdU1qWTNMamt4TlMwdU56RXhkaTB1TWpZM2JDNDNORGt0TkM0Mk1qSjJMUzR4TnpoakxqQTRNeTB1TkRRMExqVXRMamd1T1RFMUxTNDRhQzQxWXpNdU5UYzRJREFnTmk0ek1qVXRNUzQxTVNBM0xqRTFOaTAxTGprMU5TNDBNVGd0TVM0NE5qY3VNalV5TFRNdU16YzRMUzQzTkRjdE5DNDBORFV0TGpJMUxTNHpOVFV0TGpZMk5pMHVOakl5TFRFdExqZzRPU0lnWm1sc2JEMGlJekF3T1dOa1pTSXZQanh3WVhSb0lHUTlJazB4T1M0M01UVWdOaTR4TXpOakxqSTBPUzB4TGpnMk5pQXdMVE11TVRFdExqazVPUzAwTGpJMk5rTXhOeTQyTXpRdU5qSXlJREUxTGpjeU1TQXdJREV6TGpNd055QXdTRFl1TWpNMVl5MHVOREU0SURBdExqa3hOaTQwTkRRdE1TQXVPRGc1VERJdU16SXpJREl3TGpZeU1tTXdJQzR6TlRZdU1qVXVPQzQyTmpVdU9HZzBMak15T0d3eExqRTJOQzAzTGpNM09DMHVNRGd6TGpJMk4yTXVNRGcwTFM0MU16TXVOUzB1T0RnNUxqazVPQzB1T0RnNWFESXVNRGhqTkM0d056a2dNQ0EzTGpJME1TMHhMamMzT0NBNExqSTBMVFl1TnpVMUxTNHdPRE10TGpJMk55QXdMUzR6TlRZZ01DMHVOVE0wSWlCbWFXeHNQU0lqTURFeU1UWTVJaTgrUEhCaGRHZ2daRDBpVFRrdU5UWXpJRFl1TVRNell5NHdPREl0TGpJMk5pNHlOUzB1TlRNekxqUTVPQzB1TnpFdU1UWTJJREFnTGpJMUxTNHdPUzQwTVRZdExqQTVhRFV1TkRrMFl5NDJOallnTUNBeExqTXpMakE1SURFdU9ETXVNVGM0TGpFMk5pQXdJQzR6TXpNZ01DQXVORGs0TGpBNE9TNHhOamd1TURnNUxqTXpOQzR3T0RrdU5ERTRMakUzT0dndU1qVmpMakkwT0M0d09Ea3VORGszTGpJMk5pNDNORGd1TXpVMUxqSTBPQzB4TGpnMk5pQXdMVE11TVRFdExqazVPUzAwTGpNMU5VTXhOeTQzTVRjdU5UTXpJREUxTGpnd05DQXdJREV6TGpNNUlEQklOaTR5TXpWakxTNDBNVGdnTUMwdU9URTJMak0xTmkweElDNDRPRGxNTWk0ek1qTWdNakF1TmpJeVl6QWdMak0xTmk0eU5TNDRMalkyTlM0NGFEUXVNekk0YkRFdU1UWTBMVGN1TXpjNElERXVNRGcwTFRjdU9URjZJaUJtYVd4c1BTSWpNREF6TURnM0lpOCtQQzl6ZG1jKyIvPjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSI1MTIuNSIgeT0iMTc1IiB0ZXh0TGVuZ3RoPSI0NDUiIGZpbGw9IiNmZmYiPlBBWVBBTDwvdGV4dD48dGV4dCB0cmFuc2Zvcm09InNjYWxlKC4xKSIgeD0iMTI4My43NSIgeT0iMTc1IiB0ZXh0TGVuZ3RoPSI2MTcuNSIgZmlsbD0iI2ZmZiIgZm9udC13ZWlnaHQ9ImJvbGQiPlNQRU5ERU48L3RleHQ+PC9nPjwvc3ZnPg==", + "onClick": "echo 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8816166';" + }, + { + "type": "Image", + "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjI5LjUiIGhlaWdodD0iMjgiIHJvbGU9ImltZyIgYXJpYS1sYWJlbD0iTElDRU5TRTogQ0MgQlktTkMtU0EgNC4wIj48dGl0bGU+TElDRU5TRTogQ0MgQlktTkMtU0EgNC4wPC90aXRsZT48ZyBzaGFwZS1yZW5kZXJpbmc9ImNyaXNwRWRnZXMiPjxyZWN0IHdpZHRoPSI5Mi43NSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzU1NSIvPjxyZWN0IHg9IjkyLjc1IiB3aWR0aD0iMTM2Ljc1IiBoZWlnaHQ9IjI4IiBmaWxsPSIjZWY5NDIxIi8+PC9nPjxnIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJWZXJkYW5hLEdlbmV2YSxEZWphVnUgU2FucyxzYW5zLXNlcmlmIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiBmb250LXNpemU9IjEwMCI+PGltYWdlIHg9IjkiIHk9IjciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCbWFXeHNQU0lqUlVZNU5ESXhJaUJ5YjJ4bFBTSnBiV2NpSUhacFpYZENiM2c5SWpBZ01DQXlOQ0F5TkNJZ2VHMXNibk05SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpJd01EQXZjM1puSWo0OGRHbDBiR1UrUTNKbFlYUnBkbVVnUTI5dGJXOXVjend2ZEdsMGJHVStQSEJoZEdnZ1pEMGlUVEV4TGprNE15QXdZeTB6TGpJNU1pQXdMVFl1TVRrZ01TNHlNVGN0T0M0ME1qZ2dNeTQwT0RWRE1TNHlOU0ExTGpneE9TQXdJRGd1T0RRMElEQWdNVEpqTUNBekxqRTRPU0F4TGpJeE55QTJMakUwT0NBekxqVXlNaUE0TGpRMVF6VXVPREkzSURJeUxqYzFJRGd1T0RJeUlESTBJREV4TGprNE15QXlOR016TGpFMklEQWdOaTR5TWpJdE1TNHlOU0E0TGpVNU15MHpMalU0TTBNeU1pNDRNVFVnTVRndU1qRTBJREkwSURFMUxqSTROeUF5TkNBeE1tTXdMVE11TWpVMUxURXVNVGcyTFRZdU1qRTBMVE11TkRVNExUZ3VORGd6UXpFNExqSXpPQ0F4TGpJeE55QXhOUzR5TnpVZ01DQXhNUzQ1T0RNZ01IcHRMakF6TXlBeUxqRTNZekl1TnlBd0lEVXVNVEF6SURFdU1ESWdOaTQ1T0NBeUxqZzVNeUF4TGpnME15QXhMamcwTVNBeUxqZ3pJRFF1TWpjMElESXVPRE1nTmk0NU16Y2dNQ0F5TGpZNU5pMHVPVFUwSURVdU1EWXpMVEl1TnprNElEWXVPRGN5TFRFdU9UUXpJREV1T1RBMkxUUXVORFEwSURJdU9USTJMVGN1TURFeUlESXVPVEkyTFRJdU5qQXhJREF0TlM0d016Z3RNUzR3TVRrdE5pNDVNVFF0TWk0NE9UTXRNUzQ0TnpjdE1TNDROelV0TWk0NU15MDBMak0wTFRJdU9UTXROaTQ1TURVZ01DMHlMalU1TnlBeExqQTFNeTAxTGpBMk15QXlMamt6TFRZdU9UY2dNUzQ0TkRRdE1TNDROelFnTkM0eU1UUXRNaTQ0TmlBMkxqa3hOQzB5TGpnMmVrMDRMalk0SURndU1qYzRRell1TnpJeklEZ3VNamM0SURVdU1UWTFJRGt1TmpZZ05TNHhOalVnTVRKak1DQXlMak00SURFdU5EWTFJRE11TnpJeUlETXVOVGd4SURNdU56SXlJREV1TXpVNElEQWdNaTQxTVRZdExqYzBOQ0F6TGpFMU5TMHhMamczTkd3dE1TNDBPVEV0TGpjMU9HTXRMak16TXk0M09UZ3RMamd6T1NBeExqQXpOeTB4TGpRM09DQXhMakF6TnkweExqRXdOU0F3TFRFdU5qRXRMamt4TnkweExqWXhMVEl1TVRJMklEQXRNUzR5TVM0ME1qWXRNaTR4TWpjZ01TNDJNUzB5TGpFeU55NHpNaUF3SUM0NU5pNHhOek1nTVM0ek16SXVPVGRzTVM0MU9UY3RMamd6T0dNdExqWTRMVEV1TWpNMkxURXVPRE0zTFRFdU56STRMVE11TVRneExURXVOekk0ZW0wMkxqa3pNaUF3WXkweExqazFOeUF3TFRNdU5URTBJREV1TXpneUxUTXVOVEUwSURNdU56SXlJREFnTWk0ek9DQXhMalEyTkNBekxqY3lNaUF6TGpVNElETXVOekl5SURFdU16VTVJREFnTWk0MU1UWXRMamMwTkNBekxqRTFOUzB4TGpnM05Hd3RNUzQwT1MwdU56VTRZeTB1TXpNekxqYzVPQzB1T0RRZ01TNHdNemN0TVM0ME56Z2dNUzR3TXpjdE1TNHhNRFVnTUMweExqWXhNUzB1T1RFM0xURXVOakV4TFRJdU1USTJJREF0TVM0eU1TNDBNall0TWk0eE1qY2dNUzQyTVMweUxqRXlOeTR6TWlBd0lDNDVOaTR4TnpNZ01TNHpNekl1T1Rkc01TNDFPVGN0TGpnek9HTXRMalk0TFRFdU1qTTJMVEV1T0RNM0xURXVOekk0TFRNdU1UZ3hMVEV1TnpJNGVpSXZQand2YzNablBnPT0iLz48dGV4dCB0cmFuc2Zvcm09InNjYWxlKC4xKSIgeD0iNTQ4Ljc1IiB5PSIxNzUiIHRleHRMZW5ndGg9IjUxNy41IiBmaWxsPSIjZmZmIj5MSUNFTlNFPC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSIxNjExLjI1IiB5PSIxNzUiIHRleHRMZW5ndGg9IjExMjcuNSIgZmlsbD0iI2ZmZiIgZm9udC13ZWlnaHQ9ImJvbGQiPkNDIEJZLU5DLVNBIDQuMDwvdGV4dD48L2c+PC9zdmc+", + "onClick": "echo 'https://creativecommons.org/licenses/by-nc-sa/4.0/';" + } + ] + } + ] + } + ], + "status": [ + { + "code": 101, + "icon": "inactive", + "caption": "Creating instance." + }, + { + "code": 102, + "icon": "active", + "caption": "Instance active." + }, + { + "code": 104, + "icon": "inactive", + "caption": "Instance inactive." + }, + { + "code": 201, + "icon": "inactive", + "caption": "Please select a trigger to switch the gradient!" + }, + { + "code": 202, + "icon": "inactive", + "caption": "Please select at least one light!" + }, + { + "code": 203, + "icon": "inactive", + "caption": "Please select only variables with the correct profile!" + }, + { + "code": 204, + "icon": "inactive", + "caption": "Please select a valid variable for the individual lights!" + }, + { + "code": 205, + "icon": "inactive", + "caption": "Please assign a unique name for the individual lights!" + } + ] +} \ No newline at end of file diff --git a/Color Loop/locale.json b/Color Loop/locale.json new file mode 100644 index 0000000..e393a52 --- /dev/null +++ b/Color Loop/locale.json @@ -0,0 +1,40 @@ +{ + "translations": { + "de": { + "\nColor Loop\n ": "\nFarbverlauf\n ", + "The module offers the possibility to activate an automatic colour gradient or a colour change.": "Das Modul bietet die Möglichkeit, einen automatischen Farbverlauf bzw. einen Farbwechsel zu aktivieren.", + "Circuit ...": "Schaltung ...", + "Switch variable:": "Schaltervariable:", + "\nThe switching variable serves as an indicator for the switching state (on/off) of the entire lighting group (see Devices).": "\nDie Schaltvariable dient als Indikator für den Schaltzustand (An/Aus) der ganzen Leuchtgruppe (siehe Geräte).", + "Devices ...": "Geräte ...", + "Light group:": "Leuchtgruppe:", + "Lamp name": "Leuchtenname", + "Color Variables:": "Farbvariablen:", + "Status variable": "Statusvariable", + "Starting color": "Startfarbe", + "(1) Currently only variables with the profile '~HexColor' are supported.": "(1) Derzeit werden nur Variablen mit dem Profil '~HexColor' unterstützt.", + "(2) The 'Transparent' color selection causes the currently set color code to be used as the start color for the corresponding illuminant.": "(2) Die Farbauswahl 'Transparent' bewirkt die Verwendung des aktuell eingestellten Farbcodes als Startfarbe für das entsprechende Leuchtmittel.", + "(3) The lamp name is only necessary if you also want to change the start color via the webfront.": "(3) Der Leuchtenname ist nur notwendig wenn man die Startfarbe auch über das Webfront ändern möchte.", + "Advanced settings ...": "Erweiterte Einstellungen ...", + "Create variables for selection of start color per luminaire?": "Variablen für Auswahl der Startfarbe pro Leuchte anlegen?", + "In addition, create a normal switch variable to temporarily switch the colour loop on or off (e.g. for webfront)?": "Zusätzlich noch eine normale Schaltervariable anlegen zum temporären An- bzw. Ausschalten der Farbschleife (z.B. für Webfront)?", + "Transition": "Übergang", + "Increment": "Schrittweite", + "Fast": "Schnell", + "Normal": "Normal", + "Slow": "Langsam", + "Very Slow": "Sehr Langsam", + "Active": "Aktiv", + "Creating instance.": "Die Instanz wird erstellt.", + "Instance active.": "Instanz ist aktiv.", + "Instance inactive.": "Instanz ist inaktiv.", + "Please select a trigger to switch the gradient!": "Bitte wählen Sie eine Auslöser zum Schalten des Farbverlauf!", + "Please select at least one light!": "Bitte wählen Sie mindestens eine Leuchte aus!", + "Please select only variables with the correct profile!": "Bitte wählen Sie nur Variablen mit dem richtigen Profil aus!", + "Please select a valid variable for the individual lights!": "Bitte wählen Sie eine gültige Variable für die einzelnen Leuchten aus!", + "Please assign a unique name for the individual lights!": "Bitte vergeben Sie einen eindeutigen Namen für die einzelnen Leuchten!", + "Source code, donation and licence ...": "Quellcode, Spende und Lizenz ...", + "The software is free of charge for non-commercial use, I would appreciate a donation if you like the module.": "Die Software ist für die nicht kommzerielle Nutzung kostenlos, über eine Spende bei Gefallen des Moduls würde ich mich sehr freuen." + } + } +} \ No newline at end of file diff --git a/Color Loop/module.json b/Color Loop/module.json new file mode 100644 index 0000000..5fd65f5 --- /dev/null +++ b/Color Loop/module.json @@ -0,0 +1,15 @@ +{ + "id": "{67B80A2C-0E39-B6B3-E767-86E6C9AE653C}", + "name": "Color Loop", + "type": 3, + "vendor": "", + "aliases": [ + "ColorLoop", + "Farbverlauf" + ], + "parentRequirements": [], + "childRequirements": [], + "implemented": [], + "prefix": "WWXCL", + "url": "https://github.com/Wilkware/IPSymconColorLoop" +} \ No newline at end of file diff --git a/Color Loop/module.php b/Color Loop/module.php new file mode 100644 index 0000000..4721a61 --- /dev/null +++ b/Color Loop/module.php @@ -0,0 +1,325 @@ +RegisterPropertyInteger('StateVariable', 0); + // Device list + $this->RegisterPropertyString('ColorVariables', '[]'); + // Settings + $this->RegisterPropertyBoolean('CheckColor', false); + // Profiles + $this->RegisterProfile(VARIABLETYPE_INTEGER, 'WWXCL.Increment', 'Speedo', '', '', 5, 355, 5, 0); + $this->RegisterProfile(VARIABLETYPE_INTEGER, 'WWXCL.Transition', 'Repeat', '', '', 0, 0, 0, 0, $this->assoTransition); + // Status variable (active) + $exists = @$this->GetIDForIdent('active'); + $this->RegisterVariableBoolean('active', $this->Translate('Active'), '~Switch', 0); + if($exists === false) { + $this->SetValueBoolean('active', true); + } + $this->EnableAction('active'); + // Status variable (increment) + $exists = @$this->GetIDForIdent('increment'); + $this->RegisterVariableInteger('increment', $this->Translate('Increment'), 'WWXCL.Increment', 1); + if($exists === false) { + $this->SetValueInteger('increment', 5); + } + $this->EnableAction('increment'); + // Status variable (transition) + $exists = @$this->GetIDForIdent('transition'); + $vid = $this->RegisterVariableInteger('transition', $this->Translate('Transition'), 'WWXCL.Transition', 2); + if($exists === false) { + $this->SetValueInteger('transition', 5); + } + $this->EnableAction('transition'); + // Trigger + $this->RegisterTimer('ColorLoopTrigger', 0, "IPS_RequestAction(\$_IPS['TARGET'],'cycle', 0);"); + // Buffer + $this->SetBuffer('loop_data', ''); + } + + /** + * Overrides the internal IPSModule::Destroy($id) function + */ + public function Destroy() + { + //Never delete this line! + parent::Destroy(); + } + + /** + * Overrides the internal IPSModule::ApplyChanges($id) function + */ + public function ApplyChanges() + { + //Never delete this line! + parent::ApplyChanges(); + + //Delete all references in order to readd them + foreach ($this->GetReferenceList() as $referenceID) { + $this->UnregisterReference($referenceID); + } + + //Delete all registrations in order to readd them + foreach ($this->GetMessageList() as $senderID => $messages) { + foreach ($messages as $message) { + $this->UnregisterMessage($senderID, $message); + } + } + + //Register references & update messages + $variable = $this->ReadPropertyInteger('StateVariable'); + if (IPS_VariableExists($variable)) { + $this->RegisterReference($variable); + $this->RegisterMessage($variable, VM_UPDATE); + } else { + $this->SendDebug(__FUNCTION__, $variable . ' does not exist!'); + $this->SetStatus(201); + return; + } + + $json = $this->ReadPropertyString('ColorVariables'); + $this->SendDebug(__FUNCTION__, $json); + $list = json_decode($json, true); + + $count = 0; + $profile = true; + $name = true; + foreach ($list as &$line) { + if (IPS_VariableExists($line['Variable'])) { + $this->RegisterReference($line['Variable']); + if($this->GetVariableProfile($line['Variable']) != '~HexColor') { + $this->SendDebug(__FUNCTION__, $line['Variable'] . 'has wrong Profile!'); + $profile = false; + } + if(empty($line['Name'])) { + $this->SendDebug(__FUNCTION__, $line['Variable'] . 'has no Name!'); + $name = false; + } + $count++; + } + else { + $this->SendDebug(__FUNCTION__, $line['Variable'] . ' does not exist!'); + $this->SetStatus(204); + return; + } + } + // No lights + if($count == 0) { + $this->SetStatus(202); + return; + } + // Wrong Profile + if($profile != true) { + $this->SetStatus(203); + return; + } + + $color = $this->ReadPropertyBoolean('CheckColor'); + if ($color && !$name) { + $this->SetStatus(205); + return; + } + // Color Vars + $pos = 3; + foreach ($list as &$line) { + $ident = 'color_' . (string) $line['Variable']; + $this->MaintainVariable($ident, $line['Name'], VARIABLETYPE_INTEGER, '~HexColor', $pos++, $color); + if ($color) { + $this->SetValueInteger($ident, $line['Color']); + $this->EnableAction($ident); + } + } + $this->SetStatus(102); + } + + /** + * Internal SDK funktion. + * data[0] = new value + * data[1] = value changed? + * data[2] = old value + * data[3] = timestamp. + */ + public function MessageSink($timeStamp, $sender, $message, $data) + { + //$this->SendDebug(__FUNCTION__, 'SenderId: '.$sender.' Data: '.print_r($data, true), 0); + switch ($message) { + case VM_UPDATE: + // ReceiverVariable + if ($sender != $this->ReadPropertyInteger('StateVariable')) { + $this->SendDebug(__FUNCTION__, 'SenderID: ' . $sender . ' unknown!'); + } else { + if ($data[0] == true && $data[1] == true) { // OnChange on TRUE, i.e. motion detected + $this->SendDebug(__FUNCTION__, 'OnChange on TRUE - lights ON for ' . $sender); + $this->Switch(true); + } elseif ($data[0] == false && $data[1] == true) { // OnChange on FALSE, i.e. no motion + $this->SendDebug(__FUNCTION__, 'OnChange on FALSE - lights OFF for ' . $sender); + $this->Switch(false); + } else { // OnChange on FALSE, i.e. no change of status + $this->SendDebug(__FUNCTION__, 'OnChange unchanged - status not changed'); + } + } + break; + } + } + + /** + * RequestAction. + * + * @param string $ident Ident. + * @param string $value Value. + */ + public function RequestAction($ident, $value) + { + // Debug output + $this->SendDebug(__FUNCTION__, $ident . ' => ' . $value); + switch ($ident) { + case 'cycle': + $this->Cycle(); + break; + case 'active': + $this->SetValueBoolean($ident, $value); + $this->Active($value); + break; + case 'increment': + $this->SetValueInteger($ident, $value); + break; + case 'transition': + $this->SetValueInteger($ident, $value); + $this->Active($value); + break; + default: + // should only be 'color_xxxxx' + $this->SetValueInteger($ident, $value); + break; + } + return true; + } + + /** + * Activated or deactivated the color loop functionality. + * + * @param bool $value False for transition otherwise true + */ + private function Active($value) + { + $this->SendDebug(__FUNCTION__, $value); + if($value) { // Acvitvate + $vid = $this->ReadPropertyInteger('StateVariable'); + if (IPS_VariableExists($vid)) { + $value = GetValue($vid); // no modul getvalue!!! + if($value) { + $this->SendDebug(__FUNCTION__, 'Activate now!'); + $this->Switch(true); + } else { + $this->SendDebug(__FUNCTION__, 'No activation, only generally activated!'); + } + } + } else { // Deactivated + $this->SendDebug(__FUNCTION__, 'Deactivate now!'); + $this->Switch(false); + } + } + + /** + * Switch color loop ON or OFF. + * + * @param bool $value + */ + private function Switch($value) + { + $this->SendDebug(__FUNCTION__, ($value ? 'true' : 'false')); + if($value) { // ON + $ison = $this->GetValue('active'); + // only if color loop is active switched! + if($ison) { + $tran = $this->GetValue('transition'); + $this->SendDebug(__FUNCTION__, 'Trans: ' . $tran); + $ccol = $this->ReadPropertyBoolean('CheckColor'); + $json = $this->ReadPropertyString('ColorVariables'); + $list = json_decode($json, true); + $data = []; + foreach ($list as &$line) { + $varid = $line['Variable']; + $color = $line['Color']; // color from config + $ident = 'color_' . (string) $varid; + // color from status variable + if ($ccol) { + $color = $this->GetValue($ident); + } + // color is transparent then from light + if($color == -1) { + $color = GetValue($varid); + } + $data[] = [$varid, $color]; + } + $this->SendDebug(__FUNCTION__, 'Data: ' . print_r($data, true), 0); + $this->SetBuffer('loop_data', serialize($data)); + // Start Timer + $this->SetTimerInterval('ColorLoopTrigger', $tran * 1000); + } + } else { // OFF + $this->SetTimerInterval('ColorLoopTrigger', 0); + $this->SetBuffer('loop_data', ''); + } + } + + /** + * Cycle + * + */ + private function Cycle() + { + $buffer = $this->GetBuffer('loop_data'); + $last = unserialize($buffer); + $step = $this->GetValue('increment'); + $this->SendDebug(__FUNCTION__, 'Step size: ' . $step); + $next = []; + foreach($last as $index => $data) { + $this->SendDebug(__FUNCTION__, '(1): ' . $data[1]); + $rgb = $this->int2rgb($data[1]); + $this->SendDebug(__FUNCTION__, '(2): ' . $rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2]); + $hsl = $this->rgb2hsl($rgb[0], $rgb[1], $rgb[2]); + $this->SendDebug(__FUNCTION__, '(3): ' . $hsl[0] . ', ' . $hsl[1] . ', ' . $hsl[2]); + $hsl[0] = ($hsl[0] + $step) % 360; + $this->SendDebug(__FUNCTION__, '(4): ' . $hsl[0] . ', ' . $hsl[1] . ', ' . $hsl[2]); + $rgb = $this->hsl2rgb($hsl[0], $hsl[1], $hsl[2]); + $this->SendDebug(__FUNCTION__, '(5): ' . $rgb[0] . ', ' . $rgb[1] . ', ' . $rgb[2]); + $col = $this->rgb2int($rgb); + $this->SendDebug(__FUNCTION__, '(6): ' . $col); + $ret = RequestAction($data[0], $col); + $next[] = [$data[0], $col]; + } + //$this->SendDebug(__FUNCTION__, 'Data: ' . print_r($next, true), 0); + $this->SetBuffer('loop_data', serialize($next)); + } +} \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7cdbe0b --- /dev/null +++ b/LICENSE @@ -0,0 +1,438 @@ +Attribution-NonCommercial-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International +Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial-ShareAlike 4.0 International Public License +("Public License"). To the extent this Public License may be +interpreted as a contract, You are granted the Licensed Rights in +consideration of Your acceptance of these terms and conditions, and the +Licensor grants You such rights in consideration of benefits the +Licensor receives from making the Licensed Material available under +these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-NC-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution, NonCommercial, and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + l. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + m. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + n. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-NC-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + including for purposes of Section 3(b); and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/README.md b/README.md index a75b4a9..62e4925 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,126 @@ -# IPSymconColorLoop -IPS Modul +# Farbeverlauf (Color Loop) + +[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/) +[![Product](https://img.shields.io/badge/Symcon%20Version-6.0%20%3E-blue.svg)](https://www.symcon.de/produkt/) +[![Version](https://img.shields.io/badge/Modul%20Version-1.0.20230728-orange.svg)](https://github.com/Wilkware/IPSymconColorLoop) +[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/) +[![Actions](https://github.com/Wilkware/IPSymconColorLoop/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconColorLoop/actions) + +Das Modul bietet die Möglichkeit, einen automatischen Farbverlauf bzw. einen Farbwechsel zu aktivieren. Sobald sie aktiviert ist, läuft eine kontinuierliche Schleife durch verschiedene Farben, die sich fortlaufend wiederholt. + +## Inhaltverzeichnis + +1. [Funktionsumfang](#user-content-1-funktionsumfang) +2. [Voraussetzungen](#user-content-2-voraussetzungen) +3. [Installation](#user-content-3-installation) +4. [Einrichten der Instanzen in IP-Symcon](#user-content-4-einrichten-der-instanzen-in-ip-symcon) +5. [Statusvariablen und Profile](#user-content-5-statusvariablen-und-profile) +6. [WebFront](#user-content-6-webfront) +7. [PHP-Befehlsreferenz](#user-content-7-php-befehlsreferenz) +8. [Versionshistorie](#user-content-8-versionshistorie) + +### 1. Funktionsumfang + +Die Idee für das Modul stammt aus der Philips HUE App, welche ein Farbschleifen-Funktionalität bereitstellt. +Durch den Umstieg auf Zigbee2Mqtt und den Wegfall des HUE-Gateways und den damit verbunden Wegfall der HUE-App fehlte mir dieser nette Effekt. +Im Endeffekt versucht das Modul diesen Effekt nachzubilden. + +* Bilden einer Gruppe über mehrere Leuchtmittel hinweg +* Starten und stoppen der Schleife über einen hinterlegten Gruppenschalter (z.B. Z2M Group Status) +* Festlegen der Startfarbe pro Leuchte oder direktes Aufsetzen auf aktuellen Farbwert der Leuchte +* Steuerung der Funktionalität über das WebFront + * Steuerung der Farbschritte und Übergangsgeschwindigkeit + * Zeitweises Aktivieren bzw. Deaktivieren der Funktionalität + * Möglichkeit die Startfarbe pro Leuchtmittel festzulegen + +Gute Effekte kann man erzielen bei kleiner Schrittweite (5) und einem sehr langsamen Übergang (12sek) + +### 2. Voraussetzungen + +* IP-Symcon ab Version 6.0 +* Getestet mit Philips Hue Color Ambiance Leuchtmitteln + +### 3. Installation + +* Über den Modul Store das Modul _Color Loop_ installieren. +* Alternativ Über das Modul-Control folgende URL hinzufügen. +`https://github.com/Wilkware/IPSymconColorLoop` oder `git://github.com/Wilkware/IPSymconColorLoop.git` + +### 4. Einrichten der Instanzen in IP-Symcon + +* Unter 'Instanz hinzufügen' ist das _Color Loop_-Modul (Alias: _Farbverlauf_) unter dem Hersteller '(Geräte)' aufgeführt. + +__Konfigurationsseite__: + +Einstellungsbereich: + +> Schaltung ... + +Name | Beschreibung +------------------------------- | ----------------------------------------------------------------- +Schaltervariable | Die Schaltvariable, welche als Indikator für den Schaltzustand (An/Aus) der ganzen Leuchtgruppe dient. + +> Geräte ... + +Name | Beschreibung +------------------------------- | ----------------------------------------------------------------- +Leuchtgruppe (Liste) | Alle Geräte, welche an der Farbschleife beteiligt seien sollen +|- Statusvariable | Statusvariable des Leuchtmittels, welche die Farbe abbildet. Muss sich über RequestAction steuern lassen und das Profil _~HexColor_ besitzen. +|- Startfarbe | Farbwert mit dem die Farbschleife beginnen soll. Die Farbauswahl 'Transparent' bewirkt die Verwendung des aktuell eingestellten Farbcodes des Leuchtmittels als Startfarbe. +|- Leuchtenname | Der Leuchtenname ist nur notwendig wenn man die Startfarbe auch über das WebFront ändern möchte (Statusvariable). + +> Erweiterte Einstellungen ... + +Name | Beschreibung +------------------------------- | ----------------------------------------------------------------- +Variablen für Auswahl der Startfarbe pro Leuchte anlegen? | Legt pro hinterlegten Leuchtmittel eine Statusvariable an (siehe Leuchtenname) um die Startfarbe über das Webfront festlegen bzw. ändern zu können. + +### 5. Statusvariablen und Profile + +Die Statusvariablen werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. + +Name | Typ | Beschreibung +------------------------------| --------- | ---------------- +Aktiv | Boolean | Schalter für Aktivierung oder Deaktivierung der Farbschleife, d.h. soll Farbschleife starten wenn Leuchtgruppe angeschaltet wird. +Schrittweite | Integer | Auswahl, wie groß die Farbänderungsschritte erfolgen soll (in 5er Schritten zwischen 5 und 355). +Übergang | String | Auswahl, wie schnell der einzelne Farbwechsel erfolgen soll. +[Leuchtenname] | Integer | Aktivierbar über die erweiterten Einstellungen. Startfarbe fürs WebFront. + +Folgendes Profil wird angelegt: + +Name | Typ | Beschreibung +-------------------- | --------- | ---------------------- +WWXCL.Increment | Integer | Schrittweite (5 - 355) +WWXCL.Transition | Integer | Übergang in Sekunden (2, 5, 8 und 12) + +### 6. WebFront + +Man kann die Statusvariablen direkt im WF verlinken. + +### 7. PHP-Befehlsreferenz + +Das Modul stellt keine direkten Funktionsaufrufe zur Verfügung. + +### 8. Versionshistorie + +v1.0.20230728 + +* _NEU_: Initialversion + +## Entwickler + +Seit nunmehr über 10 Jahren fasziniert mich das Thema Haussteuerung. In den letzten Jahren betätige ich mich auch intensiv in der IP-Symcon Community und steuere dort verschiedenste Skript und Module bei. Ihr findet mich dort unter dem Namen @pitti ;-) + +[![GitHub](https://img.shields.io/badge/GitHub-@wilkware-181717.svg?style=for-the-badge&logo=github)](https://wilkware.github.io/) + +## Spenden + +Die Software ist für die nicht kommerzielle Nutzung kostenlos, über eine Spende bei Gefallen des Moduls würde ich mich freuen. + +[![PayPal](https://img.shields.io/badge/PayPal-spenden-00457C.svg?style=for-the-badge&logo=paypal)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8816166) + +## Lizenz + +Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 4.0 International + +[![Licence](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-EF9421.svg?style=for-the-badge&logo=creativecommons)](https://creativecommons.org/licenses/by-nc-sa/4.0/) diff --git a/library.json b/library.json new file mode 100644 index 0000000..aee8b0c --- /dev/null +++ b/library.json @@ -0,0 +1,12 @@ +{ + "id": "{FFDA8856-8685-943D-BE7C-C5EBFBDF54B0}", + "name": "Color Loop", + "author": "Wilkware (@Pitti)", + "url": "https://wilkware.de", + "compatibility": { + "version": "6.0" + }, + "version": "1.0", + "build": 20230728, + "date": 1690538400 +} \ No newline at end of file diff --git a/libs/ColorHelper.php b/libs/ColorHelper.php new file mode 100644 index 0000000..bc2e5b4 --- /dev/null +++ b/libs/ColorHelper.php @@ -0,0 +1,134 @@ + + * @copyright 2020 Heiko Wilknitz + * @link https://wilkware.de + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 + */ + +declare(strict_types=1); + +/** + * Helper class for the debug output. + */ +trait ColorHelper +{ + /** + * Convert color integer value in RGB array + * + * @param mixed $num Color value as integer. + * @return array RGB array. + */ + private function int2rgb(int $num): array + { + $rgb[0] = ($num & 0xFF0000) >> 16; + $rgb[1] = ($num & 0x00FF00) >> 8; + $rgb[2] = ($num & 0x0000FF); + return $rgb; + } + + /** + * Convert RGB array in color integer value. + * + * @param array $rgb RGB array + * @return int Color value + */ + private function rgb2int(array $rgb): int + { + $num = $rgb[0] << 16; + $num += $rgb[1] << 8; + $num += $rgb[2]; + return intval($num); + } + + /** + * Convert Hex color string in RGB array. + * + * @param string $str Hexadecimal color string + * @return array RGB array + */ + private function str2rgb(string $str): array + { + $str = preg_replace('~[^0-9a-f]~', '', $str); + $rgb = str_split($str, 2); + for($i = 0; $i < 3; $i++) { + $rgb[$i] = intval($rgb[$i], 16); + } + return $rgb; + } + + /** + * Convert RGB values in HSL array. + * + * @param int $r Red value + * @param int $g Green value + * @param int $b Blue value + * + * @return array RGB array + */ + private function rgb2hsl(int $r, int $g, int $b): array + { + $r /= 255; + $g /= 255; + $b /= 255; + $max = max($r, $g, $b); + $min = min($r, $g, $b); + + $l = ($max + $min) / 2; + $d = $max - $min; + if ($d == 0) { + $h = $s = 0; + } else { + $s = $d / (1 - abs(2 * $l - 1)); + switch ($max) { + case $r: + $h = 60 * fmod((($g - $b) / $d), 6); + if ($b > $g) $h += 360; + break; + case $g: + $h = 60 * (($b - $r) / $d + 2); + break; + case $b: + $h = 60 * (($r - $g) / $d + 4); + break; + } + } + return [intval(round($h, 0)), intval(round($s * 100, 0)), intval(round($l * 100, 0))]; + } + + /** + * Convert HSL values in RGB array. + * + * @param int $h Hue value + * @param int $s Saturation value + * @param int $l Lightness value + * + * @return array + */ + private function hsl2rgb(int $h, int $s, int $l): array + { + $c = (1 - abs(2 * ($l / 100) - 1)) * $s / 100; + $x = $c * (1 - abs(fmod(($h / 60), 2) - 1)); + $m = ($l / 100) - ($c / 2); + if ($h < 60) { + $r = $c; $g = $x; $b = 0; + } elseif ($h < 120) { + $r = $x; $g = $c; $b = 0; + } elseif ($h < 180) { + $r = 0; $g = $c; $b = $x; + } elseif ($h < 240) { + $r = 0; $g = $x; $b = $c; + } elseif ($h < 300) { + $r = $x; $g = 0; $b = $c; + } else { + $r = $c; $g = 0; $b = $x; + } + return [floor(($r + $m) * 255), floor(($g + $m) * 255), floor(($b + $m) * 255)]; + } +} diff --git a/libs/DebugHelper.php b/libs/DebugHelper.php new file mode 100644 index 0000000..c08cd1e --- /dev/null +++ b/libs/DebugHelper.php @@ -0,0 +1,56 @@ + + * @copyright 2020 Heiko Wilknitz + * @link https://wilkware.de + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 + */ + +declare(strict_types=1); + +/** + * Helper class for the debug output. + */ +trait DebugHelper +{ + /** + * Adds functionality to serialize arrays and objects. + * + * @param string $msg Title of the debug message. + * @param mixed $data Data output. + * @param int $format Output format. + */ + protected function SendDebug($msg, $data, $format = 0) + { + if (is_object($data)) { + foreach ($data as $key => $value) { + $this->SendDebug($msg . ':' . $key, $value, 1); + } + } elseif (is_array($data)) { + foreach ($data as $key => $value) { + $this->SendDebug($msg . ':' . $key, $value, 0); + } + } elseif (is_bool($data)) { + parent::SendDebug($msg, ($data ? 'TRUE' : 'FALSE'), 0); + } else { + parent::SendDebug($msg, $data, $format); + } + } + + /** + * Wrapper for default modul log messages + * + * @param string $msg Title of the log message. + * @param int $type message typ (KL_DEBUG| KL_ERROR| KL_MESSAGE| KL_NOTIFY (default)| KL_WARNING). + */ + protected function LogMessage($msg, $type = KL_NOTIFY) + { + parent::LogMessage($msg, $type); + } +} diff --git a/libs/ProfileHelper.php b/libs/ProfileHelper.php new file mode 100644 index 0000000..ddb9625 --- /dev/null +++ b/libs/ProfileHelper.php @@ -0,0 +1,203 @@ + + * @copyright 2020 Heiko Wilknitz + * @link https://wilkware.de + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 + */ + +declare(strict_types=1); + +/** + * Helper class for create variable profiles. + */ +trait ProfileHelper +{ + /** + * Create the profile for the given type, values and associations. + * + * @param string $vartype Type of the variable. + * @param string $name Profil name. + * @param string $icon Icon to display. + * @param string $prefix Variable prefix. + * @param string $suffix Variable suffix. + * @param int $minvalue Minimum value. + * @param int $maxvalue Maximum value. + * @param int $stepsize Increment. + * @param int $digits Decimal places. + * @param array $associations Associations of the values. + */ + protected function RegisterProfile($vartype, $name, $icon, $prefix = '', $suffix = '', $minvalue = 0, $maxvalue = 0, $stepsize = 0, $digits = 0, $associations = null) + { + if (!IPS_VariableProfileExists($name)) { + switch ($vartype) { + case VARIABLETYPE_BOOLEAN: + $this->RegisterProfileBoolean($name, $icon, $prefix, $suffix, $associations); + break; + case VARIABLETYPE_INTEGER: + $this->RegisterProfileInteger($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $stepsize, $digits, $associations); + break; + case VARIABLETYPE_FLOAT: + $this->RegisterProfileFloat($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $stepsize, $digits, $associations); + break; + case VARIABLETYPE_STRING: + $this->RegisterProfileString($name, $icon, $prefix, $suffix, $associations); + break; + } + } + + return $name; + } + + /** + * Create the profile for the given type with the passed name. + * + * @param string $name Profil name. + * @param string $vartype Type of the variable. + */ + protected function RegisterProfileType($name, $vartype) + { + if (!IPS_VariableProfileExists($name)) { + IPS_CreateVariableProfile($name, $vartype); + } else { + $profile = IPS_GetVariableProfile($name); + if ($profile['ProfileType'] != $vartype) { + throw new Exception('Variable profile type does not match for profile ' . $name); + } + } + } + + /** + * Create a profile for boolean values. + * + * @param string $name Profil name. + * @param string $icon Icon to display. + * @param string $prefix Variable prefix. + * @param string $suffix Variable suffix. + * @param array $asso Associations of the values. + */ + protected function RegisterProfileBoolean($name, $icon, $prefix, $suffix, $asso) + { + $this->RegisterProfileType($name, VARIABLETYPE_BOOLEAN); + + IPS_SetVariableProfileIcon($name, $icon); + IPS_SetVariableProfileText($name, $prefix, $suffix); + + if (($asso !== null) && (count($asso) !== 0)) { + foreach ($asso as $ass) { + IPS_SetVariableProfileAssociation($name, $ass[0], $this->Translate($ass[1]), $ass[2], $ass[3]); + } + } + } + + /** + * Create a profile for integer values. + * + * @param string $name Profil name. + * @param string $icon Icon to display. + * @param string $prefix Variable prefix. + * @param string $suffix Variable suffix. + * @param int $minvalue Minimum value. + * @param int $maxvalue Maximum value. + * @param int $stepsize Increment. + * @param int $digits Decimal places. + * @param array $asso Associations of the values. + */ + protected function RegisterProfileInteger($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $stepsize, $digits, $asso) + { + $this->RegisterProfileType($name, VARIABLETYPE_INTEGER); + + IPS_SetVariableProfileIcon($name, $icon); + IPS_SetVariableProfileText($name, $prefix, $suffix); + IPS_SetVariableProfileDigits($name, $digits); + + if (($asso !== null) && (count($asso) !== 0)) { + $minvalue = 0; + $maxvalue = 0; + } + IPS_SetVariableProfileValues($name, $minvalue, $maxvalue, $stepsize); + + if (($asso !== null) && (count($asso) !== 0)) { + foreach ($asso as $ass) { + IPS_SetVariableProfileAssociation($name, $ass[0], $this->Translate($ass[1]), $ass[2], $ass[3]); + } + } + } + + /** + * Create a profile for float values. + * + * @param string $name Profil name. + * @param string $icon Icon to display. + * @param string $prefix Variable prefix. + * @param string $suffix Variable suffix. + * @param int $minvalue Minimum value. + * @param int $maxvalue Maximum value. + * @param int $stepsize Increment. + * @param int $digits Decimal places. + * @param array $asso Associations of the values. + */ + protected function RegisterProfileFloat($name, $icon, $prefix, $suffix, $minvalue, $maxvalue, $stepsize, $digits, $asso) + { + $this->RegisterProfileType($name, VARIABLETYPE_FLOAT); + + IPS_SetVariableProfileIcon($name, $icon); + IPS_SetVariableProfileText($name, $prefix, $suffix); + IPS_SetVariableProfileDigits($name, $digits); + + if (($asso !== null) && (count($asso) !== 0)) { + $minvalue = 0; + $maxvalue = 0; + } + IPS_SetVariableProfileValues($name, $minvalue, $maxvalue, $stepsize); + + if (($asso !== null) && (count($asso) !== 0)) { + foreach ($asso as $ass) { + IPS_SetVariableProfileAssociation($name, $ass[0], $this->Translate($ass[1]), $ass[2], $ass[3]); + } + } + } + + /** + * Create a profile for string values. + * + * @param string $name Profil name. + * @param string $icon Icon to display. + * @param string $prefix Variable prefix. + * @param string $suffix Variable suffix. + * @param array $asso Associations of the values. + */ + protected function RegisterProfileString($name, $icon, $prefix, $suffix, $asso) + { + $this->RegisterProfileType($name, VARIABLETYPE_STRING); + + IPS_SetVariableProfileText($name, $prefix, $suffix); + IPS_SetVariableProfileIcon($name, $icon); + if (($asso !== null) && (count($asso) !== 0)) { + foreach ($asso as $ass) { + IPS_SetVariableProfileAssociation($name, $ass[0], $this->Translate($ass[1]), $ass[2], $ass[3]); + } + } + } + + /** + * Returns the used profile name of a variable + * + * @param int $id Variable ID + * @return string Empty, or name of the profile + */ + protected function GetVariableProfile($id) + { + $variableProfileName = IPS_GetVariable($id)['VariableCustomProfile']; + if ($variableProfileName == '') { + $variableProfileName = IPS_GetVariable($id)['VariableProfile']; + } + return $variableProfileName; + } +} diff --git a/libs/VariableHelper.php b/libs/VariableHelper.php new file mode 100644 index 0000000..a75adfa --- /dev/null +++ b/libs/VariableHelper.php @@ -0,0 +1,91 @@ + + * @copyright 2021 Heiko Wilknitz + * @link https://wilkware.de + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 + */ + +declare(strict_types=1); + +/** + * Helper class for access satus variables. + */ +trait VariableHelper +{ + /** + * Update a boolean value. + * + * @param string $ident Ident of the boolean variable + * @param bool $value Value of the boolean variable + */ + protected function SetValueBoolean(string $ident, bool $value) + { + $id = @$this->GetIDForIdent($ident); + if ($id !== false) { + SetValueBoolean($id, $value); + } + } + + /** + * Update a string value. + * + * @param string $ident Ident of the string variable + * @param string $value Value of the string variable + */ + protected function SetValueString(string $ident, string $value) + { + $id = @$this->GetIDForIdent($ident); + if ($id !== false) { + SetValueString($id, $value); + } + } + + /** + * Update a integer value. + * + * @param string $ident Ident of the integer variable + * @param int $value Value of the integer variable + */ + protected function SetValueInteger(string $ident, int $value) + { + $id = @$this->GetIDForIdent($ident); + if ($id !== false) { + SetValueInteger($id, $value); + } + } + + /** + * Update a float value. + * + * @param string $ident Ident of the float variable + * @param float $value Value of the float variable + */ + protected function SetValueFloat(string $ident, float $value) + { + $id = @$this->GetIDForIdent($ident); + if ($id !== false) { + SetValueFloat($id, $value); + } + } + + /** + * Sets the variable inactive. + * + * @param string $ident Ident of the integer variable + * @param bool $value Enable or disable value the variable + */ + private function SetVariableDisabled(string $ident, bool $value) + { + $id = @$this->GetIDForIdent($ident); + if ($id !== false) { + IPS_SetDisabled($id, $value); + } + } +} diff --git a/libs/_traits.php b/libs/_traits.php new file mode 100644 index 0000000..3a096ba --- /dev/null +++ b/libs/_traits.php @@ -0,0 +1,191 @@ + + * @copyright 2020 Heiko Wilknitz + * @link https://wilkware.de + * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0 + */ + +declare(strict_types=1); + +if (!defined('IPS_BASE')) { + // --- BASE MESSAGE + define('IPS_BASE', 10000); //Base Message + define('IPS_KERNELSTARTED', IPS_BASE + 1); //Post Ready Message + define('IPS_KERNELSHUTDOWN', IPS_BASE + 2); //Pre Shutdown Message, Runlevel UNINIT Follows +} +if (!defined('IPS_KERNELMESSAGE')) { + // --- KERNEL + define('IPS_KERNELMESSAGE', IPS_BASE + 100); //Kernel Message + define('KR_CREATE', IPS_KERNELMESSAGE + 1); //Kernel is beeing created + define('KR_INIT', IPS_KERNELMESSAGE + 2); //Kernel Components are beeing initialised, Modules loaded, Settings read + define('KR_READY', IPS_KERNELMESSAGE + 3); //Kernel is ready and running + define('KR_UNINIT', IPS_KERNELMESSAGE + 4); //Got Shutdown Message, unloading all stuff + define('KR_SHUTDOWN', IPS_KERNELMESSAGE + 5); //Uninit Complete, Destroying Kernel Inteface +} +if (!defined('IPS_LOGMESSAGE')) { + // --- KERNEL LOGMESSAGE + define('IPS_LOGMESSAGE', IPS_BASE + 200); //Logmessage Message + define('KL_MESSAGE', IPS_LOGMESSAGE + 1); //Normal Message | FG: Black | BG: White | STLYE : NONE + define('KL_SUCCESS', IPS_LOGMESSAGE + 2); //Success Message | FG: Black | BG: Green | STYLE : NONE + define('KL_NOTIFY', IPS_LOGMESSAGE + 3); //Notiy about Changes | FG: Black | BG: Blue | STLYE : NONE + define('KL_WARNING', IPS_LOGMESSAGE + 4); //Warnings | FG: Black | BG: Yellow | STLYE : NONE + define('KL_ERROR', IPS_LOGMESSAGE + 5); //Error Message | FG: Black | BG: Red | STLYE : BOLD + define('KL_DEBUG', IPS_LOGMESSAGE + 6); //Debug Informations + Script Results | FG: Grey | BG: White | STLYE : NONE + define('KL_CUSTOM', IPS_LOGMESSAGE + 7); //User Message | FG: Black | BG: White | STLYE : NONE +} +if (!defined('IPS_MODULEMESSAGE')) { + // --- MODULE LOADER + define('IPS_MODULEMESSAGE', IPS_BASE + 300); //ModuleLoader Message + define('ML_LOAD', IPS_MODULEMESSAGE + 1); //Module loaded + define('ML_UNLOAD', IPS_MODULEMESSAGE + 2); //Module unloaded +} +if (!defined('IPS_OBJECTMESSAGE')) { + // --- OBJECT MANAGER + define('IPS_OBJECTMESSAGE', IPS_BASE + 400); + define('OM_REGISTER', IPS_OBJECTMESSAGE + 1); //Object was registered + define('OM_UNREGISTER', IPS_OBJECTMESSAGE + 2); //Object was unregistered + define('OM_CHANGEPARENT', IPS_OBJECTMESSAGE + 3); //Parent was Changed + define('OM_CHANGENAME', IPS_OBJECTMESSAGE + 4); //Name was Changed + define('OM_CHANGEINFO', IPS_OBJECTMESSAGE + 5); //Info was Changed + define('OM_CHANGETYPE', IPS_OBJECTMESSAGE + 6); //Type was Changed + define('OM_CHANGESUMMARY', IPS_OBJECTMESSAGE + 7); //Summary was Changed + define('OM_CHANGEPOSITION', IPS_OBJECTMESSAGE + 8); //Position was Changed + define('OM_CHANGEREADONLY', IPS_OBJECTMESSAGE + 9); //ReadOnly was Changed + define('OM_CHANGEHIDDEN', IPS_OBJECTMESSAGE + 10); //Hidden was Changed + define('OM_CHANGEICON', IPS_OBJECTMESSAGE + 11); //Icon was Changed + define('OM_CHILDADDED', IPS_OBJECTMESSAGE + 12); //Child for Object was added + define('OM_CHILDREMOVED', IPS_OBJECTMESSAGE + 13); //Child for Object was removed + define('OM_CHANGEIDENT', IPS_OBJECTMESSAGE + 14); //Ident was Changed +} +if (!defined('IPS_INSTANCEMESSAGE')) { + // --- INSTANCE MANAGER + define('IPS_INSTANCEMESSAGE', IPS_BASE + 500); //Instance Manager Message + define('IM_CREATE', IPS_INSTANCEMESSAGE + 1); //Instance created + define('IM_DELETE', IPS_INSTANCEMESSAGE + 2); //Instance deleted + define('IM_CONNECT', IPS_INSTANCEMESSAGE + 3); //Instance connectged + define('IM_DISCONNECT', IPS_INSTANCEMESSAGE + 4); //Instance disconncted + define('IM_CHANGESTATUS', IPS_INSTANCEMESSAGE + 5); //Status was Changed + define('IM_CHANGESETTINGS', IPS_INSTANCEMESSAGE + 6); //Settings were Changed + define('IM_CHANGESEARCH', IPS_INSTANCEMESSAGE + 7); //Searching was started/stopped + define('IM_SEARCHUPDATE', IPS_INSTANCEMESSAGE + 8); //Searching found new results + define('IM_SEARCHPROGRESS', IPS_INSTANCEMESSAGE + 9); //Searching progress in % + define('IM_SEARCHCOMPLETE', IPS_INSTANCEMESSAGE + 10); //Searching is complete +} +if (!defined('IPS_VARIABLEMESSAGE')) { + // --- VARIABLE MANAGER + define('IPS_VARIABLEMESSAGE', IPS_BASE + 600); //Variable Manager Message + define('VM_CREATE', IPS_VARIABLEMESSAGE + 1); //Variable Created + define('VM_DELETE', IPS_VARIABLEMESSAGE + 2); //Variable Deleted + define('VM_UPDATE', IPS_VARIABLEMESSAGE + 3); //On Variable Update + define('VM_CHANGEPROFILENAME', IPS_VARIABLEMESSAGE + 4); //On Profile Name Change + define('VM_CHANGEPROFILEACTION', IPS_VARIABLEMESSAGE + 5); //On Profile Action Change +} +if (!defined('IPS_SCRIPTMESSAGE')) { + // --- SCRIPT MANAGER + define('IPS_SCRIPTMESSAGE', IPS_BASE + 700); //Script Manager Message + define('SM_CREATE', IPS_SCRIPTMESSAGE + 1); //On Script Create + define('SM_DELETE', IPS_SCRIPTMESSAGE + 2); //On Script Delete + define('SM_CHANGEFILE', IPS_SCRIPTMESSAGE + 3); //On Script File changed + define('SM_BROKEN', IPS_SCRIPTMESSAGE + 4); //Script Broken Status changed +} +if (!defined('IPS_EVENTMESSAGE')) { + // --- EVENT MANAGER + define('IPS_EVENTMESSAGE', IPS_BASE + 800); //Event Scripter Message + define('EM_CREATE', IPS_EVENTMESSAGE + 1); //On Event Create + define('EM_DELETE', IPS_EVENTMESSAGE + 2); //On Event Delete + define('EM_UPDATE', IPS_EVENTMESSAGE + 3); + define('EM_CHANGEACTIVE', IPS_EVENTMESSAGE + 4); + define('EM_CHANGELIMIT', IPS_EVENTMESSAGE + 5); + define('EM_CHANGESCRIPT', IPS_EVENTMESSAGE + 6); + define('EM_CHANGETRIGGER', IPS_EVENTMESSAGE + 7); + define('EM_CHANGETRIGGERVALUE', IPS_EVENTMESSAGE + 8); + define('EM_CHANGETRIGGEREXECUTION', IPS_EVENTMESSAGE + 9); + define('EM_CHANGECYCLIC', IPS_EVENTMESSAGE + 10); + define('EM_CHANGECYCLICDATEFROM', IPS_EVENTMESSAGE + 11); + define('EM_CHANGECYCLICDATETO', IPS_EVENTMESSAGE + 12); + define('EM_CHANGECYCLICTIMEFROM', IPS_EVENTMESSAGE + 13); + define('EM_CHANGECYCLICTIMETO', IPS_EVENTMESSAGE + 14); +} +if (!defined('IPS_MEDIAMESSAGE')) { + // --- MEDIA MANAGER + define('IPS_MEDIAMESSAGE', IPS_BASE + 900); //Media Manager Message + define('MM_CREATE', IPS_MEDIAMESSAGE + 1); //On Media Create + define('MM_DELETE', IPS_MEDIAMESSAGE + 2); //On Media Delete + define('MM_CHANGEFILE', IPS_MEDIAMESSAGE + 3); //On Media File changed + define('MM_AVAILABLE', IPS_MEDIAMESSAGE + 4); //Media Available Status changed + define('MM_UPDATE', IPS_MEDIAMESSAGE + 5); +} +if (!defined('IPS_LINKMESSAGE')) { + // --- LINK MANAGER + define('IPS_LINKMESSAGE', IPS_BASE + 1000); //Link Manager Message + define('LM_CREATE', IPS_LINKMESSAGE + 1); //On Link Create + define('LM_DELETE', IPS_LINKMESSAGE + 2); //On Link Delete + define('LM_CHANGETARGET', IPS_LINKMESSAGE + 3); //On Link TargetID change +} +if (!defined('IPS_FLOWMESSAGE')) { + // --- DATA HANDLER + define('IPS_FLOWMESSAGE', IPS_BASE + 1100); //Data Handler Message + define('FM_CONNECT', IPS_FLOWMESSAGE + 1); //On Instance Connect + define('FM_DISCONNECT', IPS_FLOWMESSAGE + 2); //On Instance Disconnect +} +if (!defined('IPS_ENGINEMESSAGE')) { + // --- SCRIPT ENGINE + define('IPS_ENGINEMESSAGE', IPS_BASE + 1200); //Script Engine Message + define('SE_UPDATE', IPS_ENGINEMESSAGE + 1); //On Library Refresh + define('SE_EXECUTE', IPS_ENGINEMESSAGE + 2); //On Script Finished execution + define('SE_RUNNING', IPS_ENGINEMESSAGE + 3); //On Script Started execution +} +if (!defined('IPS_PROFILEMESSAGE')) { + // --- PROFILE POOL + define('IPS_PROFILEMESSAGE', IPS_BASE + 1300); + define('PM_CREATE', IPS_PROFILEMESSAGE + 1); + define('PM_DELETE', IPS_PROFILEMESSAGE + 2); + define('PM_CHANGETEXT', IPS_PROFILEMESSAGE + 3); + define('PM_CHANGEVALUES', IPS_PROFILEMESSAGE + 4); + define('PM_CHANGEDIGITS', IPS_PROFILEMESSAGE + 5); + define('PM_CHANGEICON', IPS_PROFILEMESSAGE + 6); + define('PM_ASSOCIATIONADDED', IPS_PROFILEMESSAGE + 7); + define('PM_ASSOCIATIONREMOVED', IPS_PROFILEMESSAGE + 8); + define('PM_ASSOCIATIONCHANGED', IPS_PROFILEMESSAGE + 9); +} +if (!defined('IPS_TIMERMESSAGE')) { + // --- TIMER POOL + define('IPS_TIMERMESSAGE', IPS_BASE + 1400); //Timer Pool Message + define('TM_REGISTER', IPS_TIMERMESSAGE + 1); + define('TM_UNREGISTER', IPS_TIMERMESSAGE + 2); + define('TM_SETINTERVAL', IPS_TIMERMESSAGE + 3); + define('TM_UPDATE', IPS_TIMERMESSAGE + 4); + define('TM_RUNNING', IPS_TIMERMESSAGE + 5); +} +if (!defined('IS_ACTIVE')) { //Nur wenn Konstanten noch nicht bekannt sind. + // --- STATUS CODES + define('IS_SBASE', 100); + define('IS_CREATING', IS_SBASE + 1); //module is being created + define('IS_ACTIVE', IS_SBASE + 2); //module created and running + define('IS_DELETING', IS_SBASE + 3); //module us being deleted + define('IS_INACTIVE', IS_SBASE + 4); //module is not beeing used +// --- ERROR CODES + define('IS_EBASE', 200); //default errorcode + define('IS_NOTCREATED', IS_EBASE + 1); //instance could not be created +} +if (!defined('vtBoolean')) { //Nur wenn Konstanten noch nicht bekannt sind. + define('vtBoolean', 0); + define('vtInteger', 1); + define('vtFloat', 2); + define('vtString', 3); +} + +/** + * Include all helper trait classes. + */ +require_once __DIR__ . '/../libs/ColorHelper.php'; +require_once __DIR__ . '/../libs/DebugHelper.php'; +require_once __DIR__ . '/../libs/ProfileHelper.php'; +require_once __DIR__ . '/../libs/VariableHelper.php';