mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
Create Effect configuration files (.json) with JSON RPC (#277)
* Add getEffectSchemas and loadEffectSchema function * Add getEffectSchemas function * add effect schema files to internal resources * Add loadEffectSchema and getEffectSchemas function * add effect schema resources * add getEffectSchemas function * extend handleSchemaGetCommand to get ... ... all available effect schemas add handleCreateEffectCommand function * add handleCreateEffectCommand function * include schema-create-effect.json file * add create-effect schema * Add schema-create-effect.json file * Add createEffect to hyperion-remote * Add createEffect function * add createEffect function * Create fade.schema.json * Add files via upload * Add files via upload * Update police.schema.json * Update EffectEngine.qrc.in * Update CMakeLists.txt
This commit is contained in:
parent
4faa505fa4
commit
fab0c208fe
42
effects/schema/fade.schema.json
Normal file
42
effects/schema/fade.schema.json
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "fade.py",
|
||||||
|
"title":"Fade",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"fade-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Fade Time",
|
||||||
|
"default": 5.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"color-start": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color Start",
|
||||||
|
"default": "255,174,11",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"color-end": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color End",
|
||||||
|
"default": "100,100,100",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
36
effects/schema/knight-rider.schema.json
Normal file
36
effects/schema/knight-rider.schema.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "knight-rider.py",
|
||||||
|
"title":"Knight Rider",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"speed": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Speed",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum": 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"fadeFactor": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Fade Factor",
|
||||||
|
"default": 0.7,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
15
effects/schema/light-clock.schema.json
Normal file
15
effects/schema/light-clock.schema.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "light-clock.py",
|
||||||
|
"title":"Light clock",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"show_seconds": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Show seconds",
|
||||||
|
"default": true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
87
effects/schema/mood-blobs.schema.json
Normal file
87
effects/schema/mood-blobs.schema.json
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "mood-blobs.py",
|
||||||
|
"title":"Mood Blobs",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"blobs": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"Blob count",
|
||||||
|
"default": 5,
|
||||||
|
"minimum" : 1,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"rotationTime": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 20.0,
|
||||||
|
"minimum" : 1.0,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"hueChange": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Hue change",
|
||||||
|
"default": 60.0,
|
||||||
|
"minimum" : 1.0,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Reverse direction",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"colorRandom": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Random color",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"baseChange": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Base color change",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 7
|
||||||
|
},
|
||||||
|
"baseColorRangeLeft": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"baseColorRangeLeft",
|
||||||
|
"default": 0.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 360.0,
|
||||||
|
"append" : "° (Degree)",
|
||||||
|
"propertyOrder" : 8
|
||||||
|
},
|
||||||
|
"baseColorRangeRight": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"baseColorRangeRight",
|
||||||
|
"default": 360.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 360.0,
|
||||||
|
"append" : "° (Degree)",
|
||||||
|
"propertyOrder" : 9
|
||||||
|
},
|
||||||
|
"baseColorChangeRate": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"baseColorChangeRate",
|
||||||
|
"default": 2.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"append" : "Seconds for one degree",
|
||||||
|
"propertyOrder" : 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
54
effects/schema/police.schema.json
Normal file
54
effects/schema/police.schema.json
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "police.py",
|
||||||
|
"title":"Police",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"color_one": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color one",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"color_two": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color two",
|
||||||
|
"default": "0,0,255",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"colors_count": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"Colors count",
|
||||||
|
"default": "10",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"rotation-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 2.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Reverse direction",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
29
effects/schema/rainbow-mood.schema.json
Normal file
29
effects/schema/rainbow-mood.schema.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "rainbow-mood.py",
|
||||||
|
"title":"Rainbow mood",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"rotation-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 60.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"brightness": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Brightness",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Reverse",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
36
effects/schema/rainbow-swirl.schema.json
Normal file
36
effects/schema/rainbow-swirl.schema.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "rainbow-swirl.py",
|
||||||
|
"title":"Rainbow swirl",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"rotation-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation Time",
|
||||||
|
"default": 20.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"center_x": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Center X",
|
||||||
|
"default": 0.5,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"center_y": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Center Y",
|
||||||
|
"default": 0.5,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Reverse",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
23
effects/schema/random.schema.json
Normal file
23
effects/schema/random.schema.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "random.py",
|
||||||
|
"title":"Random",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"speed": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Speed",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"saturation": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Saturation",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
32
effects/schema/running_dots.schema.json
Normal file
32
effects/schema/running_dots.schema.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "running_dots.py",
|
||||||
|
"title":"Running dots",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"speed": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Runner speed",
|
||||||
|
"default": 1.5,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"colorLevel": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"Color",
|
||||||
|
"default": 220,
|
||||||
|
"minimium" : 0,
|
||||||
|
"maximum" : 255,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"whiteLevel": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"White",
|
||||||
|
"default": 0,
|
||||||
|
"minimium" : 0,
|
||||||
|
"maximum" : 254,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
48
effects/schema/shutdown.schema.json
Normal file
48
effects/schema/shutdown.schema.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "shutdown.py",
|
||||||
|
"title":"System Shutdown",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"speed": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Speed",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"alarm-color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Alarm color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"post-color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Post color",
|
||||||
|
"default": "255,174,11",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"shutdown-enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Shutdown enabled",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
35
effects/schema/snake.schema.json
Normal file
35
effects/schema/snake.schema.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "snake.py",
|
||||||
|
"title":"Snake",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"rotation-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 12.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"percentage": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"Percentage",
|
||||||
|
"default": 10,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
62
effects/schema/sparks.schema.json
Normal file
62
effects/schema/sparks.schema.json
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "sparks.py",
|
||||||
|
"title":"Sparks",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"color_one": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"rotation-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 2.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"sleep-time": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 0.05,
|
||||||
|
"minimum" : 0.01,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"brightness": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.01,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"saturation": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Rotation time",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.01,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"reverse": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Reverse direction",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"random-color": {
|
||||||
|
"type": "boolean",
|
||||||
|
"title":"Random color",
|
||||||
|
"default": false,
|
||||||
|
"propertyOrder" : 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
30
effects/schema/strobe.schema.json
Normal file
30
effects/schema/strobe.schema.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "strobe.py",
|
||||||
|
"title":"Strobe",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"color": {
|
||||||
|
"type": "array",
|
||||||
|
"title":"Color",
|
||||||
|
"default": "255,0,0",
|
||||||
|
"items" : {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 255
|
||||||
|
},
|
||||||
|
"minItems": 3,
|
||||||
|
"maxItems": 3,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"frequency": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Frequency",
|
||||||
|
"default": 10.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"append" : "Hz",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
16
effects/schema/traces.schema.json
Normal file
16
effects/schema/traces.schema.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "traces.py",
|
||||||
|
"title":"Color traces",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"speed": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Speed",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
22
effects/schema/udp.schema.json
Normal file
22
effects/schema/udp.schema.json
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "udp.py",
|
||||||
|
"title":"UDP listener",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"ListenPort": {
|
||||||
|
"type": "Integer",
|
||||||
|
"title":"Listen Port",
|
||||||
|
"default": 2801,
|
||||||
|
"minimum" : 1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"ListenIP": {
|
||||||
|
"type": "string",
|
||||||
|
"title":"Listen IP",
|
||||||
|
"default": "",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
16
effects/schema/x-mas.schema.json
Normal file
16
effects/schema/x-mas.schema.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"script" : "x-mas.py",
|
||||||
|
"title":"X-Mas",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"sleepTime": {
|
||||||
|
"type": "number",
|
||||||
|
"title":"Sleep Time",
|
||||||
|
"default": 1.0,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
@ -14,6 +14,7 @@
|
|||||||
// Effect engine includes
|
// Effect engine includes
|
||||||
#include <effectengine/EffectDefinition.h>
|
#include <effectengine/EffectDefinition.h>
|
||||||
#include <effectengine/ActiveEffectDefinition.h>
|
#include <effectengine/ActiveEffectDefinition.h>
|
||||||
|
#include <effectengine/EffectSchema.h>
|
||||||
#include <utils/Logger.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
// pre-declarioation
|
// pre-declarioation
|
||||||
@ -32,8 +33,12 @@ public:
|
|||||||
|
|
||||||
const std::list<ActiveEffectDefinition> & getActiveEffects();
|
const std::list<ActiveEffectDefinition> & getActiveEffects();
|
||||||
|
|
||||||
|
const std::list<EffectSchema> & getEffectSchemas();
|
||||||
|
|
||||||
static bool loadEffectDefinition(const QString & path, const QString & effectConfigFile, EffectDefinition &effectDefinition);
|
static bool loadEffectDefinition(const QString & path, const QString & effectConfigFile, EffectDefinition &effectDefinition);
|
||||||
|
|
||||||
|
static bool loadEffectSchema(const QString & path, const QString & effectSchemaFile, EffectSchema &effectSchema);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
/// Run the specified effect on the given priority channel and optionally specify a timeout
|
||||||
int runEffect(const QString &effectName, int priority, int timeout = -1);
|
int runEffect(const QString &effectName, int priority, int timeout = -1);
|
||||||
@ -63,6 +68,8 @@ private:
|
|||||||
|
|
||||||
std::list<ActiveEffectDefinition> _availableActiveEffects;
|
std::list<ActiveEffectDefinition> _availableActiveEffects;
|
||||||
|
|
||||||
|
std::list<EffectSchema> _effectSchemas;
|
||||||
|
|
||||||
PyThreadState * _mainThreadState;
|
PyThreadState * _mainThreadState;
|
||||||
|
|
||||||
Logger * _log;
|
Logger * _log;
|
||||||
|
11
include/effectengine/EffectSchema.h
Normal file
11
include/effectengine/EffectSchema.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// QT include
|
||||||
|
#include <QString>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
struct EffectSchema
|
||||||
|
{
|
||||||
|
QString pyFile, schemaFile;
|
||||||
|
QJsonObject pySchema;
|
||||||
|
};
|
@ -29,6 +29,7 @@
|
|||||||
// Effect engine includes
|
// Effect engine includes
|
||||||
#include <effectengine/EffectDefinition.h>
|
#include <effectengine/EffectDefinition.h>
|
||||||
#include <effectengine/ActiveEffectDefinition.h>
|
#include <effectengine/ActiveEffectDefinition.h>
|
||||||
|
#include <effectengine/EffectSchema.h>
|
||||||
|
|
||||||
// KodiVideoChecker includes
|
// KodiVideoChecker includes
|
||||||
#include <kodivideochecker/KODIVideoChecker.h>
|
#include <kodivideochecker/KODIVideoChecker.h>
|
||||||
@ -126,6 +127,10 @@ public:
|
|||||||
/// @return The list of active effects
|
/// @return The list of active effects
|
||||||
const std::list<ActiveEffectDefinition> &getActiveEffects();
|
const std::list<ActiveEffectDefinition> &getActiveEffects();
|
||||||
|
|
||||||
|
/// Get the list of available effect schema files
|
||||||
|
/// @return The list of available effect schema files
|
||||||
|
const std::list<EffectSchema> &getEffectSchemas();
|
||||||
|
|
||||||
/// gets the current json config object
|
/// gets the current json config object
|
||||||
/// @return json config
|
/// @return json config
|
||||||
const QJsonObject& getQJsonConfig() { return _qjsonConfig; };
|
const QJsonObject& getQJsonConfig() { return _qjsonConfig; };
|
||||||
|
@ -82,6 +82,22 @@ EffectEngine::EffectEngine(Hyperion * hyperion, const QJsonObject & jsonEffectCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Info(_log, "%d effects loaded from directory %s", efxCount, path.toUtf8().constData());
|
Info(_log, "%d effects loaded from directory %s", efxCount, path.toUtf8().constData());
|
||||||
|
|
||||||
|
// collect effect schemas
|
||||||
|
efxCount = 0;
|
||||||
|
directory = path + "schema/";
|
||||||
|
QStringList pynames = directory.entryList(QStringList() << "*.json", QDir::Files, QDir::Name | QDir::IgnoreCase);
|
||||||
|
foreach (const QString & pyname, pynames)
|
||||||
|
{
|
||||||
|
EffectSchema pyEffect;
|
||||||
|
if (loadEffectSchema(path, pyname, pyEffect))
|
||||||
|
{
|
||||||
|
_effectSchemas.push_back(pyEffect);
|
||||||
|
efxCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (efxCount > 0)
|
||||||
|
Info(_log, "%d effect schemas loaded from directory %s", efxCount, (path + "schema/").toUtf8().constData());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -138,6 +154,11 @@ const std::list<ActiveEffectDefinition> &EffectEngine::getActiveEffects()
|
|||||||
return _availableActiveEffects;
|
return _availableActiveEffects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::list<EffectSchema> &EffectEngine::getEffectSchemas()
|
||||||
|
{
|
||||||
|
return _effectSchemas;
|
||||||
|
}
|
||||||
|
|
||||||
bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition)
|
bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effectConfigFile, EffectDefinition & effectDefinition)
|
||||||
{
|
{
|
||||||
Logger * log = Logger::getInstance("EFFECTENGINE");
|
Logger * log = Logger::getInstance("EFFECTENGINE");
|
||||||
@ -233,16 +254,92 @@ bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effe
|
|||||||
if (scriptName.isEmpty())
|
if (scriptName.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
QFile fileInfo(scriptName);
|
||||||
|
|
||||||
if (scriptName.mid(0, 1) == ":" )
|
if (scriptName.mid(0, 1) == ":" )
|
||||||
effectDefinition.script = ":/effects/"+scriptName.mid(1);
|
{
|
||||||
else
|
(!fileInfo.exists())
|
||||||
effectDefinition.script = path + QDir::separator().toLatin1() + scriptName;
|
? effectDefinition.script = ":/effects/"+scriptName.mid(1)
|
||||||
|
: effectDefinition.script = scriptName;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
(!fileInfo.exists())
|
||||||
|
? effectDefinition.script = path + QDir::separator().toLatin1() + scriptName
|
||||||
|
: effectDefinition.script = scriptName;
|
||||||
|
}
|
||||||
|
|
||||||
effectDefinition.args = config["args"].toObject();
|
effectDefinition.args = config["args"].toObject();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EffectEngine::loadEffectSchema(const QString &path, const QString &effectSchemaFile, EffectSchema & effectSchema)
|
||||||
|
{
|
||||||
|
Logger * log = Logger::getInstance("EFFECTENGINE");
|
||||||
|
|
||||||
|
QString fileName = path + "schema/" + QDir::separator() + effectSchemaFile;
|
||||||
|
QJsonParseError error;
|
||||||
|
|
||||||
|
// ---------- Read the effect schema file ----------
|
||||||
|
|
||||||
|
QFile file(fileName);
|
||||||
|
if (!file.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
Error( log, "Effect schema '%s' could not be loaded", fileName.toUtf8().constData());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray fileContent = file.readAll();
|
||||||
|
QJsonDocument schemaEffect = QJsonDocument::fromJson(fileContent, &error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
// report to the user the failure and their locations in the document.
|
||||||
|
int errorLine(0), errorColumn(0);
|
||||||
|
|
||||||
|
for( int i=0, count=qMin( error.offset,fileContent.size()); i<count; ++i )
|
||||||
|
{
|
||||||
|
++errorColumn;
|
||||||
|
if(fileContent.at(i) == '\n' )
|
||||||
|
{
|
||||||
|
errorColumn = 0;
|
||||||
|
++errorLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Error( log, "Error while reading effect schema: '%s' at Line: '%i' , Column: %i", error.errorString().toUtf8().constData(), errorLine, errorColumn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
// ---------- setup the definition ----------
|
||||||
|
|
||||||
|
QJsonObject tempSchemaEffect = schemaEffect.object();
|
||||||
|
QString scriptName = tempSchemaEffect["script"].toString();
|
||||||
|
effectSchema.schemaFile = fileName;
|
||||||
|
fileName = path + QDir::separator() + scriptName;
|
||||||
|
QFile pyFile(fileName);
|
||||||
|
|
||||||
|
if (scriptName.isEmpty() || !pyFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
fileName = path + "schema/" + QDir::separator() + effectSchemaFile;
|
||||||
|
Error( log, "Python script '%s' in effect schema '%s' could not be loaded", scriptName.toUtf8().constData(), fileName.toUtf8().constData());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pyFile.close();
|
||||||
|
|
||||||
|
if (scriptName.mid(0, 1) == ":" )
|
||||||
|
effectSchema.pyFile = ":/effects/"+scriptName.mid(1);
|
||||||
|
else
|
||||||
|
effectSchema.pyFile = path + QDir::separator().toLatin1() + scriptName;
|
||||||
|
|
||||||
|
effectSchema.pySchema = tempSchemaEffect;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int EffectEngine::runEffect(const QString &effectName, int priority, int timeout)
|
int EffectEngine::runEffect(const QString &effectName, int priority, int timeout)
|
||||||
{
|
{
|
||||||
return runEffect(effectName, QJsonObject(), priority, timeout);
|
return runEffect(effectName, QJsonObject(), priority, timeout);
|
||||||
|
@ -814,6 +814,11 @@ const std::list<ActiveEffectDefinition> & Hyperion::getActiveEffects()
|
|||||||
return _effectEngine->getActiveEffects();
|
return _effectEngine->getActiveEffects();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::list<EffectSchema> & Hyperion::getEffectSchemas()
|
||||||
|
{
|
||||||
|
return _effectEngine->getEffectSchemas();
|
||||||
|
}
|
||||||
|
|
||||||
int Hyperion::setEffect(const QString &effectName, int priority, int timeout)
|
int Hyperion::setEffect(const QString &effectName, int priority, int timeout)
|
||||||
{
|
{
|
||||||
return _effectEngine->runEffect(effectName, priority, timeout);
|
return _effectEngine->runEffect(effectName, priority, timeout);
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
// hyperion util includes
|
// hyperion util includes
|
||||||
#include <hyperion/ImageProcessorFactory.h>
|
#include <hyperion/ImageProcessorFactory.h>
|
||||||
@ -282,6 +283,8 @@ void JsonClientConnection::handleMessage(const QString& messageString)
|
|||||||
handleImageCommand(message, command, tan);
|
handleImageCommand(message, command, tan);
|
||||||
else if (command == "effect")
|
else if (command == "effect")
|
||||||
handleEffectCommand(message, command, tan);
|
handleEffectCommand(message, command, tan);
|
||||||
|
else if (command == "create-effect")
|
||||||
|
handleCreateEffectCommand(message, command, tan);
|
||||||
else if (command == "serverinfo")
|
else if (command == "serverinfo")
|
||||||
handleServerInfoCommand(message, command, tan);
|
handleServerInfoCommand(message, command, tan);
|
||||||
else if (command == "clear")
|
else if (command == "clear")
|
||||||
@ -434,6 +437,65 @@ void JsonClientConnection::handleEffectCommand(const QJsonObject& message, const
|
|||||||
sendSuccessReply(command, tan);
|
sendSuccessReply(command, tan);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::handleCreateEffectCommand(const QJsonObject& message, const QString &command, const int tan)
|
||||||
|
{
|
||||||
|
struct find_schema: std::unary_function<EffectSchema, bool>
|
||||||
|
{
|
||||||
|
QString pyFile;
|
||||||
|
find_schema(QString pyFile):pyFile(pyFile) { }
|
||||||
|
bool operator()(EffectSchema const& schema) const
|
||||||
|
{
|
||||||
|
return schema.pyFile == pyFile;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(message.size() > 0)
|
||||||
|
{
|
||||||
|
if (!message["args"].toObject().isEmpty())
|
||||||
|
{
|
||||||
|
QString scriptName;
|
||||||
|
(message["script"].toString().mid(0, 1) == ":" )
|
||||||
|
? scriptName = ":/effects//" + message["script"].toString().mid(1)
|
||||||
|
: scriptName = message["script"].toString();
|
||||||
|
|
||||||
|
std::list<EffectSchema> effectsSchemas = _hyperion->getEffectSchemas();
|
||||||
|
std::list<EffectSchema>::iterator it = std::find_if(effectsSchemas.begin(), effectsSchemas.end(), find_schema(scriptName));
|
||||||
|
|
||||||
|
if (it != effectsSchemas.end())
|
||||||
|
{
|
||||||
|
QString errors;
|
||||||
|
|
||||||
|
if (!checkJson(message["args"].toObject(), it->schemaFile, errors))
|
||||||
|
{
|
||||||
|
sendErrorReply("Error while validating json: " + errors, command, tan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject effectJson;
|
||||||
|
QJsonArray effectArray;
|
||||||
|
effectArray = _hyperion->getQJsonConfig()["effects"].toObject()["paths"].toArray();
|
||||||
|
|
||||||
|
if (effectArray.size() > 0)
|
||||||
|
{
|
||||||
|
effectJson["name"] = message["name"].toString();
|
||||||
|
effectJson["script"] = message["script"].toString();
|
||||||
|
effectJson["args"] = message["args"].toObject();
|
||||||
|
QJsonFactory::writeJson(effectArray[0].toString() + QDir::separator() + message["name"].toString().replace(QString(" "), QString("")) + QString(".json"), effectJson);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
sendErrorReply("Can't save new effect. Effect path empty", command, tan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSuccessReply(command, tan);
|
||||||
|
} else
|
||||||
|
sendErrorReply("Missing schema file for Python script " + message["script"].toString(), command, tan);
|
||||||
|
} else
|
||||||
|
sendErrorReply("Missing or empty Object 'args'", command, tan);
|
||||||
|
} else
|
||||||
|
sendErrorReply("Error while parsing json: Message size " + QString(message.size()), command, tan);
|
||||||
|
}
|
||||||
|
|
||||||
void JsonClientConnection::handleServerInfoCommand(const QJsonObject&, const QString& command, const int tan)
|
void JsonClientConnection::handleServerInfoCommand(const QJsonObject&, const QString& command, const int tan)
|
||||||
{
|
{
|
||||||
// create result
|
// create result
|
||||||
@ -939,7 +1001,7 @@ void JsonClientConnection::handleSchemaGetCommand(const QJsonObject& message, co
|
|||||||
Q_INIT_RESOURCE(resource);
|
Q_INIT_RESOURCE(resource);
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
|
|
||||||
// read the json schema from the resource
|
// read the hyperion json schema from the resource
|
||||||
QFile schemaData(":/hyperion-schema");
|
QFile schemaData(":/hyperion-schema");
|
||||||
|
|
||||||
if (!schemaData.open(QIODevice::ReadOnly))
|
if (!schemaData.open(QIODevice::ReadOnly))
|
||||||
@ -976,10 +1038,43 @@ void JsonClientConnection::handleSchemaGetCommand(const QJsonObject& message, co
|
|||||||
|
|
||||||
schemaJson = doc.object();
|
schemaJson = doc.object();
|
||||||
|
|
||||||
//QJsonObject.insert can not merge. See details: http://doc.qt.io/qt-5/qjsonobject.html#insert
|
// collect all LED Devices
|
||||||
properties = schemaJson["properties"].toObject();
|
properties = schemaJson["properties"].toObject();
|
||||||
alldevices = LedDevice::getLedDeviceSchemas();
|
alldevices = LedDevice::getLedDeviceSchemas();
|
||||||
properties.insert("alldevices", alldevices);
|
properties.insert("alldevices", alldevices);
|
||||||
|
|
||||||
|
// collect all available effect schemas
|
||||||
|
QJsonObject pyEffectSchemas, pyEffectSchema;
|
||||||
|
QJsonArray in, ex;
|
||||||
|
const std::list<EffectSchema> & effectsSchemas = _hyperion->getEffectSchemas();
|
||||||
|
for (const EffectSchema & effectSchema : effectsSchemas)
|
||||||
|
{
|
||||||
|
if (effectSchema.pyFile.mid(0, 1) == ":")
|
||||||
|
{
|
||||||
|
QJsonObject internal;
|
||||||
|
internal.insert("script", effectSchema.pyFile);
|
||||||
|
internal.insert("schema-location", effectSchema.schemaFile);
|
||||||
|
internal.insert("schema-content", effectSchema.pySchema);
|
||||||
|
in.append(internal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QJsonObject external;
|
||||||
|
external.insert("script", effectSchema.pyFile);
|
||||||
|
external.insert("schema-location", effectSchema.schemaFile);
|
||||||
|
external.insert("schema-content", effectSchema.pySchema);
|
||||||
|
ex.append(external);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in.empty())
|
||||||
|
pyEffectSchema.insert("internal", in);
|
||||||
|
if (!ex.empty())
|
||||||
|
pyEffectSchema.insert("external", ex);
|
||||||
|
|
||||||
|
pyEffectSchemas = pyEffectSchema;
|
||||||
|
properties.insert("effectSchemas", pyEffectSchemas);
|
||||||
|
|
||||||
schemaJson.insert("properties", properties);
|
schemaJson.insert("properties", properties);
|
||||||
|
|
||||||
result["result"] = schemaJson;
|
result["result"] = schemaJson;
|
||||||
|
@ -89,6 +89,13 @@ private:
|
|||||||
///
|
///
|
||||||
void handleEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
void handleEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Handle an incoming JSON Effect message (Write JSON Effect)
|
||||||
|
///
|
||||||
|
/// @param message the incoming message
|
||||||
|
///
|
||||||
|
void handleCreateEffectCommand(const QJsonObject & message, const QString &command, const int tan);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Handle an incoming JSON Server info message
|
/// Handle an incoming JSON Server info message
|
||||||
///
|
///
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
<file alias="schema-temperature">schema/schema-temperature.json</file>
|
<file alias="schema-temperature">schema/schema-temperature.json</file>
|
||||||
<file alias="schema-adjustment">schema/schema-adjustment.json</file>
|
<file alias="schema-adjustment">schema/schema-adjustment.json</file>
|
||||||
<file alias="schema-effect">schema/schema-effect.json</file>
|
<file alias="schema-effect">schema/schema-effect.json</file>
|
||||||
|
<file alias="schema-create-effect">schema/schema-create-effect.json</file>
|
||||||
<file alias="schema-sourceselect">schema/schema-sourceselect.json</file>
|
<file alias="schema-sourceselect">schema/schema-sourceselect.json</file>
|
||||||
<file alias="schema-config">schema/schema-config.json</file>
|
<file alias="schema-config">schema/schema-config.json</file>
|
||||||
<file alias="schema-componentstate">schema/schema-componentstate.json</file>
|
<file alias="schema-componentstate">schema/schema-componentstate.json</file>
|
||||||
|
30
libsrc/jsonserver/schema/schema-create-effect.json
Normal file
30
libsrc/jsonserver/schema/schema-create-effect.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"required":true,
|
||||||
|
"properties":{
|
||||||
|
"command": {
|
||||||
|
"type" : "string",
|
||||||
|
"required" : true,
|
||||||
|
"enum" : ["create-effect"]
|
||||||
|
},
|
||||||
|
"tan" : {
|
||||||
|
"type" : "integer"
|
||||||
|
},
|
||||||
|
"name" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"required" : true
|
||||||
|
},
|
||||||
|
"script" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"required" : true
|
||||||
|
},
|
||||||
|
"args" :
|
||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"required" : true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
"command": {
|
"command": {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"required" : true,
|
"required" : true,
|
||||||
"enum" : ["color", "image", "effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment", "sourceselect", "config", "componentstate", "ledcolors"]
|
"enum" : ["color", "image", "effect", "create-effect", "serverinfo", "clear", "clearall", "transform", "correction", "temperature", "adjustment", "sourceselect", "config", "componentstate", "ledcolors"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,9 +148,10 @@ void JsonConnection::setEffect(const QString &effectName, const QString & effect
|
|||||||
}
|
}
|
||||||
|
|
||||||
effect["args"] = doc.object();
|
effect["args"] = doc.object();
|
||||||
command["effect"] = effect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
command["effect"] = effect;
|
||||||
|
|
||||||
if (duration > 0)
|
if (duration > 0)
|
||||||
{
|
{
|
||||||
command["duration"] = duration;
|
command["duration"] = duration;
|
||||||
@ -163,6 +164,51 @@ void JsonConnection::setEffect(const QString &effectName, const QString & effect
|
|||||||
parseReply(reply);
|
parseReply(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonConnection::createEffect(const QString &effectName, const QString &effectScript, const QString & effectArgs)
|
||||||
|
{
|
||||||
|
qDebug() << "Create effect " << effectName;
|
||||||
|
|
||||||
|
// create command
|
||||||
|
QJsonObject effect;
|
||||||
|
effect["command"] = QString("create-effect");
|
||||||
|
effect["name"] = effectName;
|
||||||
|
effect["script"] = effectScript;
|
||||||
|
|
||||||
|
if (effectArgs.size() > 0)
|
||||||
|
{
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(effectArgs.toUtf8() ,&error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError)
|
||||||
|
{
|
||||||
|
// report to the user the failure and their locations in the document.
|
||||||
|
int errorLine(0), errorColumn(0);
|
||||||
|
|
||||||
|
for( int i=0, count=qMin( error.offset,effectArgs.size()); i<count; ++i )
|
||||||
|
{
|
||||||
|
++errorColumn;
|
||||||
|
if(effectArgs.at(i) == '\n' )
|
||||||
|
{
|
||||||
|
errorColumn = 0;
|
||||||
|
++errorLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream sstream;
|
||||||
|
sstream << "Error in effect arguments: " << error.errorString().toStdString() << " at Line: " << errorLine << ", Column: " << errorColumn;
|
||||||
|
throw std::runtime_error(sstream.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
effect["args"] = doc.object();
|
||||||
|
}
|
||||||
|
|
||||||
|
// send command message
|
||||||
|
QJsonObject reply = sendMessage(effect);
|
||||||
|
|
||||||
|
// parse reply message
|
||||||
|
parseReply(reply);
|
||||||
|
}
|
||||||
|
|
||||||
QString JsonConnection::getServerInfo()
|
QString JsonConnection::getServerInfo()
|
||||||
{
|
{
|
||||||
qDebug() << "Get server info";
|
qDebug() << "Get server info";
|
||||||
|
@ -56,6 +56,15 @@ public:
|
|||||||
///
|
///
|
||||||
void setEffect(const QString & effectName, const QString &effectArgs, int priority, int duration);
|
void setEffect(const QString & effectName, const QString &effectArgs, int priority, int duration);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Create a effect configuration file (.json)
|
||||||
|
///
|
||||||
|
/// @param effectName The name of the effect
|
||||||
|
/// @param effectScript The name of the Python effect file
|
||||||
|
/// @param effectArgs The arguments of the effect
|
||||||
|
///
|
||||||
|
void createEffect(const QString &effectName, const QString &effectScript, const QString & effectArgs);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Retrieve a list of all occupied priority channels
|
/// Retrieve a list of all occupied priority channels
|
||||||
///
|
///
|
||||||
|
@ -56,13 +56,15 @@ int main(int argc, char * argv[])
|
|||||||
// create the option parser and initialize all parameters
|
// create the option parser and initialize all parameters
|
||||||
Parser parser("Simple application to send a command to hyperion using the Json interface");
|
Parser parser("Simple application to send a command to hyperion using the Json interface");
|
||||||
|
|
||||||
Option & argAddress = parser.add<Option> ('a', "address" , "Set the address of the hyperion server [default: %1]", "localhost:19444");
|
Option & argAddress = parser.add<Option> ('a', "address" , "Set the address of the hyperion server [default: %1]", "localhost:19444");
|
||||||
IntOption & argPriority = parser.add<IntOption> ('p', "priority" , "Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]", "100");
|
IntOption & argPriority = parser.add<IntOption> ('p', "priority" , "Use to the provided priority channel (the lower the number, the higher the priority) [default: %1]", "100");
|
||||||
IntOption & argDuration = parser.add<IntOption> ('d', "duration" , "Specify how long the leds should be switched on in milliseconds [default: infinity]");
|
IntOption & argDuration = parser.add<IntOption> ('d', "duration" , "Specify how long the leds should be switched on in milliseconds [default: infinity]");
|
||||||
ColorsOption & argColor = parser.add<ColorsOption> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex getColors or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
|
ColorsOption & argColor = parser.add<ColorsOption> ('c', "color" , "Set all leds to a constant color (either RRGGBB hex getColors or a color name. The color may be repeated multiple time like: RRGGBBRRGGBB)");
|
||||||
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the leds to the colors according to the given image file");
|
ImageOption & argImage = parser.add<ImageOption> ('i', "image" , "Set the leds to the colors according to the given image file");
|
||||||
Option & argEffect = parser.add<Option> ('e', "effect" , "Enable the effect with the given name");
|
Option & argEffect = parser.add<Option> ('e', "effect" , "Enable the effect with the given name");
|
||||||
|
Option & argEffectFile = parser.add<Option> (0x0, "effectFile", "Arguments to use in combination with --createEffect");
|
||||||
Option & argEffectArgs = parser.add<Option> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.", "");
|
Option & argEffectArgs = parser.add<Option> (0x0, "effectArgs", "Arguments to use in combination with the specified effect. Should be a Json object string.", "");
|
||||||
|
Option & argCreateEffect= parser.add<Option> (0x0, "createEffect","Write a new Json Effect configuration file.\nFirst parameter = Effect name.\nSecond parameter = Effect file (--effectFile).\nLast parameter = Effect arguments (--effectArgs.)", "");
|
||||||
BooleanOption & argServerInfo = parser.add<BooleanOption>('l', "list" , "List server info and active effects with priority and duration");
|
BooleanOption & argServerInfo = parser.add<BooleanOption>('l', "list" , "List server info and active effects with priority and duration");
|
||||||
BooleanOption & argClear = parser.add<BooleanOption>('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
BooleanOption & argClear = parser.add<BooleanOption>('x', "clear" , "Clear data for the priority channel provided by the -p option");
|
||||||
BooleanOption & argClearAll = parser.add<BooleanOption>(0x0, "clearall" , "Clear data for all active priority channels");
|
BooleanOption & argClearAll = parser.add<BooleanOption>(0x0, "clearall" , "Clear data for all active priority channels");
|
||||||
@ -92,12 +94,12 @@ int main(int argc, char * argv[])
|
|||||||
Option & argConfigSet = parser.add<Option> ('W', "configSet", "Write to the actual loaded configuration file. Should be a Json object string.");
|
Option & argConfigSet = parser.add<Option> ('W', "configSet", "Write to the actual loaded configuration file. Should be a Json object string.");
|
||||||
|
|
||||||
// parse all _options
|
// parse all _options
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
// check if we need to display the usage. exit if we do.
|
// check if we need to display the usage. exit if we do.
|
||||||
if (parser.isSet(argHelp))
|
if (parser.isSet(argHelp))
|
||||||
{
|
{
|
||||||
parser.showHelp(0);
|
parser.showHelp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if at least one of the available color transforms is set
|
// check if at least one of the available color transforms is set
|
||||||
@ -106,13 +108,14 @@ int main(int argc, char * argv[])
|
|||||||
bool colorModding = colorTransform || colorAdjust;
|
bool colorModding = colorTransform || colorAdjust;
|
||||||
|
|
||||||
// check that exactly one command was given
|
// check that exactly one command was given
|
||||||
int commandCount = count({parser.isSet(argColor), parser.isSet(argImage), parser.isSet(argEffect), parser.isSet(argServerInfo), parser.isSet(argClear), parser.isSet(argClearAll), parser.isSet(argEnableComponent), parser.isSet(argDisableComponent), colorModding, parser.isSet(argSource), parser.isSet(argSourceAuto), parser.isSet(argSourceOff), parser.isSet(argConfigGet), parser.isSet(argSchemaGet), parser.isSet(argConfigSet)});
|
int commandCount = count({parser.isSet(argColor), parser.isSet(argImage), parser.isSet(argEffect), parser.isSet(argCreateEffect), parser.isSet(argServerInfo), parser.isSet(argClear), parser.isSet(argClearAll), parser.isSet(argEnableComponent), parser.isSet(argDisableComponent), colorModding, parser.isSet(argSource), parser.isSet(argSourceAuto), parser.isSet(argSourceOff), parser.isSet(argConfigGet), parser.isSet(argSchemaGet), parser.isSet(argConfigSet)});
|
||||||
if (commandCount != 1)
|
if (commandCount != 1)
|
||||||
{
|
{
|
||||||
qWarning() << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:";
|
qWarning() << (commandCount == 0 ? "No command found." : "Multiple commands found.") << " Provide exactly one of the following options:";
|
||||||
showHelp(argColor);
|
showHelp(argColor);
|
||||||
showHelp(argImage);
|
showHelp(argImage);
|
||||||
showHelp(argEffect);
|
showHelp(argEffect);
|
||||||
|
showHelp(argCreateEffect);
|
||||||
showHelp(argServerInfo);
|
showHelp(argServerInfo);
|
||||||
showHelp(argClear);
|
showHelp(argClear);
|
||||||
showHelp(argClearAll);
|
showHelp(argClearAll);
|
||||||
@ -156,6 +159,10 @@ int main(int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
connection.setEffect(argEffect.value(parser), argEffectArgs.value(parser), argPriority.getInt(parser), argDuration.getInt(parser));
|
connection.setEffect(argEffect.value(parser), argEffectArgs.value(parser), argPriority.getInt(parser), argDuration.getInt(parser));
|
||||||
}
|
}
|
||||||
|
else if (parser.isSet(argCreateEffect))
|
||||||
|
{
|
||||||
|
connection.createEffect(argCreateEffect.value(parser), argEffectFile.value(parser), argEffectArgs.value(parser));
|
||||||
|
}
|
||||||
else if (parser.isSet(argServerInfo))
|
else if (parser.isSet(argServerInfo))
|
||||||
{
|
{
|
||||||
QString info = connection.getServerInfo();
|
QString info = connection.getServerInfo();
|
||||||
|
Loading…
Reference in New Issue
Block a user