----------------------------------------------------------------------------------------------------------------- --PluginInfo ----------------------------------------------------------------------------------------------------------------- PluginInfo = { Name = "Sennheiser~TCCM Ceiling Microphone", Manufacturer = "Sennheiser", Version = "1.0.0", Id = "SENNHEISER_TCCM_TCP_Control", Description = "HTTPS Control of Sennheiser TCCM Ceiling Microphone", Type = Reflect and Reflect.Types.Power or 0, ShowDebug = true } ----------------------------------------------------------------------------------------------------------------- --Colors ----------------------------------------------------------------------------------------------------------------- local Colors = { White = {255, 255, 255}, Black = {0, 0, 0}, Grey = {75, 75, 75}, DarkGrey = {25, 25, 25}, Blue = {0, 128, 255}, PowderBlue = {59, 132, 224}, Yellow = {255, 255, 0}, Red = {255, 0, 0}, Green = {0, 255, 0} } RedAlt = "#D2042D" YellowAlt = "#FDDA0D" GreenAlt = "#32CD32" GreyAlt = "#191919" ----------------------------------------------------------------------------------------------------------------- --Commands to Device ----------------------------------------------------------------------------------------------------------------- apiDeviceSite = "/api/device/site" apiDeviceIdentification = "/api/device/identification" --apiDeviceState = "/api/device/state" apiDeviceIdentity = "/api/device/identity" apiFirmwareUpdateState = "/api/firmware/update/state" apiDeviceLED = "/api/device/leds/ring" apiAudioInputsMicLevel = "/api/audio/inputs/microphone/level" apiAudioOutputsLevel = "/api/audio/outputs/analog" apiAudioMute = "/api/audio/outputs/global/mute" apiAudioEqualizer = "/api/audio/equalizer" apiAudioVoiceLift = "/api/audio/outputs/dante/local" apiAudioInputMicSensitivity = "/api/audio/inputs/microphone/beam" apiAudioInputMicBeam = "/api/audio/inputs/microphone/beam/direction" apiAudioInputMicExclusionZones = "/api/audio/inputs/microphone/exclusionZones" apiAudioInputMicPriorityZones = "/api/audio/inputs/microphone/priorityZones/0" IdentifySet = '{"visual": true}' IdentifyReset = '{"visual": false}' ----------------------------------------------------------------------------------------------------------------- --Graphics and Icons ----------------------------------------------------------------------------------------------------------------- SennheiserLogo = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgdmlld0JveD0iMCAwIDQzOC4yNDkzOSA1OS4wNjI1IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmcxMCIKICAgc29kaXBvZGk6ZG9jbmFtZT0ic2VubmhlaXNlcl9sb2dvLnN2ZyIKICAgd2lkdGg9IjQzOC4yNDkzOSIKICAgaGVpZ2h0PSI1OS4wNjI1IgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkyLjUgKDIwNjBlYzFmOWYsIDIwMjAtMDQtMDgpIj4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGExNCI+CiAgICA8cmRmOlJERj4KICAgICAgPGNjOldvcmsKICAgICAgICAgcmRmOmFib3V0PSIiPgogICAgICAgIDxkYzpmb3JtYXQ+aW1hZ2Uvc3ZnK3htbDwvZGM6Zm9ybWF0PgogICAgICAgIDxkYzp0eXBlCiAgICAgICAgICAgcmRmOnJlc291cmNlPSJodHRwOi8vcHVybC5vcmcvZGMvZGNtaXR5cGUvU3RpbGxJbWFnZSIgLz4KICAgICAgPC9jYzpXb3JrPgogICAgPC9yZGY6UkRGPgogIDwvbWV0YWRhdGE+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSIxNDU2IgogICAgIGlua3NjYXBlOndpbmRvdy1oZWlnaHQ9Ijc2MiIKICAgICBpZD0ibmFtZWR2aWV3MTIiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjAuNSIKICAgICBpbmtzY2FwZTpjeD0iNDE5Ljc5MDE2IgogICAgIGlua3NjYXBlOmN5PSIyOS41MzEyNSIKICAgICBpbmtzY2FwZTp3aW5kb3cteD0iNDUiCiAgICAgaW5rc2NhcGU6d2luZG93LXk9IjM1IgogICAgIGlua3NjYXBlOndpbmRvdy1tYXhpbWl6ZWQ9IjAiCiAgICAgaW5rc2NhcGU6Y3VycmVudC1sYXllcj0ic3ZnMTAiIC8+CiAgPGRlZnMKICAgICBpZD0iZGVmczQiPgogICAgPHN0eWxlCiAgICAgICBpZD0ic3R5bGUyIj4KICAgICAgLmEgewogICAgICAgIGZpbGw6ICNmZmY7CiAgICAgICAgZmlsbC1ydWxlOiBldmVub2RkOwogICAgICB9CiAgICA8L3N0eWxlPgogIDwvZGVmcz4KICA8dGl0bGUKICAgICBpZD0idGl0bGU2Ij5TZW5uaGVpc2VyTG9nb0xpbmVfbmVnPC90aXRsZT4KICA8cGF0aAogICAgIGNsYXNzPSJhIgogICAgIGQ9Im0gMjM0Ljg3MDA1LDEyLjkxMjE4OCBoIDYuNDI3MTkgdiAzMy4yNTU0OTEgaCAtOC4xODI2MSBsIC05LjUzNDU4LC0xNS4zMDA0OTIgYyAtMS42MzI1MiwtMi42MjM3ODEgLTMuMDIxOSwtNS41MTA3NDEgLTMuMDIxOSwtNS41MTA3NDEgbCAtMC4wOTYyLDAuMDMzNCB2IDIwLjc3NzgzNiBoIC02LjQyNzIgViAxMi45MTIxODggaCA3LjU1NDczIGwgMTEuMjg0NjYsMTguMTE3OTg0IGEgMjQuMTgwNDY5LDI0LjE4MDQ2OSAwIDAgMSAxLjkzNTc4LDMuNzUzOTg0IGwgMC4wNjE0LC0wLjAzMzQgeiBtIDM2Ljk0OTM2LDEzLjYxODU0NiBoIC0xMS4xOTExNiB2IC0xMy42MzcyNSBoIC04LjE1ODU2IHYgMzMuMjU4MTY0IGggOC4xNTg1NiBWIDMxLjk1OTk4NCBoIDExLjE5MTE2IHYgMTQuMTkxNjY0IGggOC4yMDI2NSBWIDEyLjg5MzQ4NCBoIC04LjIwMjY1IHogbSAtMTE5LjQ5NTU5LDUuMTc0MDg3IGggMTAuNjExMzMgdiAtNS4wMDE3NSBoIC0xMC42MTEzMyB2IC04LjY2MDg4NCBoIDE0LjE5Njk5IHYgLTUuMTI5OTk5IGggLTIyLjM3OTYyIHYgMzMuMjU0MTU2IGggMjIuNjM0NzkgdiAtNS41NDY4MTMgaCAtMTQuNDUyMTYgeiBtIC0yOS40NzQ4LC0xMS4yMjE4NzUgYSAxLjQ4MTU1NDcsMS40ODE1NTQ2IDAgMCAxIDEuMjIxMDQsLTIuNDQwNzU5IGggMTIuMTY1MDUgdiAtNS4xMzEzMzUgaCAtMTQuNDEyMDkgYSA3LjA5NzgzNiw3LjA5NzgzNTkgMCAwIDAgLTcuMzAzNTcsNi42MTgyMzQgYyAwLDEuOTQ3Nzk3IDAuMTQ4MjgsMy4zNjkyMzUgMy4wNzI2Niw2LjQzNjU0NyBsIDEwLjgzODQ1LDExLjM1NTQ2OSBhIDEuODM2OTE0MSwxLjgzNjkxNCAwIDAgMSAtMS4yMTk3LDMuMjk3MDk0IEggMTEzLjgxMTQgdiA1LjU1MDgyIGggMTUuMjgxNzkgYSA3Ljg3NDAxNTYsNy44NzQwMTU2IDAgMCAwIDguMTMwNTIsLTcuODE1MjM1IGMgMCwtMi4xOTg5NTIgLTAuNTE1NjcsLTMuNjc3ODM1IC0zLjQyMTMzLC02LjY3MzAwOCB6IG0gNzMuNTgzNDQsMTQuMjY2NDc1IC0wLjA2MTQsMC4wMzM0IGEgMjQuMTgwNDY5LDI0LjE4MDQ2OSAwIDAgMCAtMS45MzU3NywtMy43NTM5ODQgTCAxODMuMTUwNTcsMTIuOTEyMTg4IGggLTcuNTU0NzMgdiAzMy4yNTU0OTEgaCA2LjQyNzE5IFYgMjUuMzg5ODQ0IGwgMC4wOTYyLC0wLjAzMzQgYyAwLDAgMS4zODgwNCwyLjg4Njk2IDMuMDIxODksNS41MTA3NDIgbCA5LjUzNDU5LDE1LjI5OTE1NiBoIDguMTgyNjEgViAxMi45MTIxODggaCAtNi40MjcxOCB6IG0gMTgwLjQ4NTE1LC0zLjA0NzI3MyBoIDEwLjYxMTM2IHYgLTQuOTk5MDc3IGggLTEwLjYwNjAxIHYgLTguNjYwODg0IGggMTQuMTk3IFYgMTIuOTEyMTg4IEggMzY4LjczOSB2IDMzLjI1NDE1NiBoIDIyLjYzNDc5IHYgLTUuNTQ2ODEzIGggLTE0LjQ1MDgzIHogbSA1MC4zNzU1NCwxNC40NjQxOTYgaCAtOC44ODkzNCBsIC02LjM4NTc3LC0xMy42NTMyODEgaCAtMy41ODI5OSBsIDAuMDA5LDEzLjY1MzI4MSBoIC04LjE2OTQ5IFYgMTIuOTEyMTg4IGggMTQuOTEyNzcgYyA3LjE4NjAyLDAgMTAuNTIxODUsNC40NzAwNDYgMTAuNTIxODUsOS42NDE0NiBhIDkuNTQxMjY2MSw5LjU0MTI2NjEgMCAwIDEgLTYuNDEyNSw5LjAwOTU2MyB6IG0gLTguNTgzNCwtMjMuMzk3NjEgYyAwLC0xLjUyOTY0OCAtMC44OTc3NSwtNC43MjM4NzQgLTUuMjEwMTYsLTQuNzIzODc0IGggLTUuMDY3MjEgdiA5LjQ1NTc2NSBoIDQuOTY5NjggYyA0LjQ5Mjc3LC0wLjAwMjYgNS4zMTMwMywtMy4yNzcwNTQgNS4zMTMwMywtNC43MzA1NTQgeiBNIDM0Ny4zNDUzLDIwLjQ4Mjk0NiBhIDEuNDgxNTU0NywxLjQ4MTU1NDYgMCAwIDEgMS4yMjEwNSwtMi40NDA3NTggaCAxMi4xNjUwNSB2IC01LjEzMTMzNiBoIC0xNC40MTA3NiBhIDcuMDk3ODM2LDcuMDk3ODM1OSAwIDAgMCAtNy4zMDM1Nyw2LjYxODIzNCBjIDAsMS45NDc3OTcgMC4xNDgyOSwzLjM2OTIzNSAzLjA3MjY1LDYuNDM2NTQ3IGwgMTAuODM4NDcsMTEuMzU1NDY5IGEgMS44MzY5MTQxLDEuODM2OTE0IDAgMCAxIC0xLjIxOTcxLDMuMjk3MDk0IGggLTEzLjM5OTQ2IHYgNS41NTA4MiBoIDE1LjI4MTggYSA3Ljg3NDAxNTYsNy44NzQwMTU2IDAgMCAwIDguMTMwNSwtNy44MTUyMzUgYyAwLC0yLjE5ODk1MiAtMC41MTU2NywtMy42Nzc4MzUgLTMuNDIxMzQsLTYuNjczMDA4IHogbSAtNDcuOTY4MTcsMTEuMjIxODc1IGggMTAuNjExMzYgdiAtNS4wMDE3NSBoIC0xMC42MDMzNCB2IC04LjY2MDg4NCBoIDE0LjE5NyB2IC01LjEyOTk5OSBoIC0yMi4zODYzIHYgMzMuMjU0MTU2IGggMjIuNjM0OCB2IC01LjU0NjgxMyBoIC0xNC40NDU1IHogbSAyMy4zNjAyLDE0LjQ2NDE5NSBoIDguMTc1OTQgViAxMi45MTA4NTIgaCAtOC4xNzU5NCB6IE0gMTAuOTU2MjM1LDEuNDc2NTYyNSBWIDU3LjU4NTkzNyBoIDc0LjgxMjUgViAxLjQ3NjU2MjUgWiBtIDQxLjE2ODI1LDUuMTc0MDg1NyB2IDAgYyAtNC40NDYsMS43MDQ2NTYzIC04LjcxOTY2NCw1LjQ3NzM0MzggLTEyLjE2NzcxOSwxMy4wNDAwODU4IC0wLjk5NjYwOSwyLjE4NTU5NCAtMi44ODAyODEsNi40MzEyMDMgLTMuNzQwNjI1LDguMzI4MjM1IEMgMjkuMjc5OTUzLDQzLjIyNzI4MSAyNS43MzAzNjgsNDYuNDk3NjU2IDE1LjI3Mzk4NSw0Ni40OTc2NTYgViA1LjY4NjEwMTggaCAzNi42NzI4MTkgYSAwLjQ5ODMwNDY5LDAuNDk4MzA0NjkgMCAwIDEgMC4xNzc2ODEsMC45NjQ1NDY0IHogbSAyOS4zMjY1LDUuOTE0MTk1OCBWIDUzLjM3NjM5OCBIIDQ0Ljc3NjgyOCBhIDAuNDk4MzA0NjksMC40OTgzMDQ2OSAwIDAgMSAtMC4xNzc2OCwtMC45NjQ1NDYgdiAwIGMgNC40NDczMzYsLTEuNzA0NjU2IDguNzE4MzI4LC01LjQ3NzM0NCAxMi4xNjc3MiwtMTMuMDQwMDg3IDAuOTk2NjA4LC0yLjE4NTU5NCAyLjg4MDI4LC02LjQzMTIwMyAzLjc0MDYyNSwtOC4zMjgyMzQgNi45Mzc1MjIsLTE1LjIwODMxMiAxMC40ODcxMDgsLTE4LjQ3ODY4NyAyMC45NDM0OTIsLTE4LjQ3ODY4NyB6IgogICAgIGlkPSJwYXRoOCIKICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1ydWxlOmV2ZW5vZGQ7c3Ryb2tlLXdpZHRoOjEuMzM1OTM3NSIgLz4KPC9zdmc+Cg==" TCCMIcon = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdGVkIGJ5IEljb01vb24uaW8gLS0+Cgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHZlcnNpb249IjEuMSIKICAgd2lkdGg9IjMyIgogICBoZWlnaHQ9IjMyIgogICB2aWV3Qm94PSIwIDAgMzIgMzIiCiAgIGlkPSJzdmc2IgogICBzb2RpcG9kaTpkb2NuYW1lPSJtaWMtY2VpbGluZ193aGl0ZS5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTIuNSAoMjA2MGVjMWY5ZiwgMjAyMC0wNC0wOCkiPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTEyIj4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT5taWMtY2VpbGluZzwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMxMCIgLz4KICA8c29kaXBvZGk6bmFtZWR2aWV3CiAgICAgcGFnZWNvbG9yPSIjZmZmZmZmIgogICAgIGJvcmRlcmNvbG9yPSIjNjY2NjY2IgogICAgIGJvcmRlcm9wYWNpdHk9IjEiCiAgICAgb2JqZWN0dG9sZXJhbmNlPSIxMCIKICAgICBncmlkdG9sZXJhbmNlPSIxMCIKICAgICBndWlkZXRvbGVyYW5jZT0iMTAiCiAgICAgaW5rc2NhcGU6cGFnZW9wYWNpdHk9IjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp3aW5kb3ctd2lkdGg9Ijc3MiIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI0ODAiCiAgICAgaWQ9Im5hbWVkdmlldzgiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjcuMzc1IgogICAgIGlua3NjYXBlOmN4PSIxNiIKICAgICBpbmtzY2FwZTpjeT0iMTYiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjQ1IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIzNSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIwIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzYiIC8+CiAgPHRpdGxlCiAgICAgaWQ9InRpdGxlMiI+bWljLWNlaWxpbmc8L3RpdGxlPgogIDxwYXRoCiAgICAgZD0iTTE2Ljk5MyAxNi4wNTBsNy4wNTAtNy4wNTAtMC45NDMtMC45NDMtNy4wNTAgNy4wNTAtNy4wNTAtNy4wNTAtMC45NDMgMC45NDMgNy4wNTAgNy4wNTAtNy4wNTAgNy4wNTAgMC45NDMgMC45NDMgNy4wNTAtNy4wNTAgNy4wNTAgNy4wNTAgMC45NDMtMC45NDMtNy4wNTAtNy4wNTB6TTQgMi42NjdoMjRjMC43MzYgMCAxLjMzMyAwLjU5NyAxLjMzMyAxLjMzM3YyNGMwIDAuNzM2LTAuNTk3IDEuMzMzLTEuMzMzIDEuMzMzaC0yNGMtMC43MzYgMC0xLjMzMy0wLjU5Ny0xLjMzMy0xLjMzM3YtMjRjMC0wLjczNiAwLjU5Ny0xLjMzMyAxLjMzMy0xLjMzM3pNNC4zOTEgNS4zMzNsMS44ODYgMS44ODYgMC45NDMtMC45NDMtMS44ODYtMS44ODYtMC45NDMgMC45NDN6TTI3LjYwOSAyNi42NjdsLTEuODg2LTEuODg2LTAuOTQzIDAuOTQzIDEuODg2IDEuODg2IDAuOTQzLTAuOTQzek0yNy42MDkgNS4zMzNsLTAuOTQzLTAuOTQzLTEuODg2IDEuODg2IDAuOTQzIDAuOTQzIDEuODg2LTEuODg2ek00LjM5MSAyNi42NjdsMC45NDMgMC45NDMgMS44ODYtMS44ODYtMC45NDMtMC45NDMtMS44ODYgMS44ODZ6IgogICAgIGlkPSJwYXRoNCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmIiAvPgo8L3N2Zz4K" IdentifyModeInactive = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdGVkIGJ5IEljb01vb24uaW8gLS0+Cgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHZlcnNpb249IjEuMSIKICAgd2lkdGg9IjMyIgogICBoZWlnaHQ9IjMyIgogICB2aWV3Qm94PSIwIDAgMzIgMzIiCiAgIGlkPSJzdmczODE2IgogICBzb2RpcG9kaTpkb2NuYW1lPSJpZGVudGlmeVdoaXRlSW5hY3RpdmUuc3ZnIgogICBpbmtzY2FwZTp2ZXJzaW9uPSIwLjkyLjUgKDIwNjBlYzFmOWYsIDIwMjAtMDQtMDgpIj4KICA8bWV0YWRhdGEKICAgICBpZD0ibWV0YWRhdGEzODIyIj4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT5pZGVudGlmeTwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxkZWZzCiAgICAgaWQ9ImRlZnMzODIwIiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMSIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTg3NSIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDE0IgogICAgIGlkPSJuYW1lZHZpZXczODE4IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIyNS44MTI1IgogICAgIGlua3NjYXBlOmN4PSIxNiIKICAgICBpbmtzY2FwZTpjeT0iMTYiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9IjQ1IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIzNSIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzM4MTYiIC8+CiAgPHRpdGxlCiAgICAgaWQ9InRpdGxlMzgxMiI+aWRlbnRpZnk8L3RpdGxlPgogIDxwYXRoCiAgICAgZD0ibSAxNS45MjE1MTgsMjAuOTA2ODUgYyAtMi45NDUsMCAtNS4zMzMsLTIuMzg2IC01LjMzMywtNS4zMzQgMCwtMi45NDUgMi4zODgsLTUuMzMyIDUuMzMzLC01LjMzMiAyLjk0NywwIDUuMzM0LDIuMzg3IDUuMzM0LDUuMzMyIDAsMi45NDkgLTIuMzg4LDUuMzM0IC01LjMzNCw1LjMzNCB2IDAgMCB6IG0gMCwyIGMgNi42NDQsMCAxMy4zMzQsLTUuODc0IDEzLjMzNCwtNy4zMzMgMCwtMS40NTkgLTYuNjksLTcuMzMzMDAwMSAtMTMuMzM0LC03LjMzMzAwMDEgLTYuNjQyOTk5OCwwIC0xMy4zMzI5OTk4LDUuNzg2MDAwMSAtMTMuMzMyOTk5OCw3LjMzMzAwMDEgMCwxLjU0NyA2LjY5LDcuMzMzIDEzLjMzMjk5OTgsNy4zMzMgeiBtIDAsLTEwIGMgLTEuNDcsMCAtMi42NjYsMS4xOTYgLTIuNjY2LDIuNjY2IDAsMS40NzEgMS4xOTYsMi42NjggMi42NjYsMi42NjggMS40NywwIDIuNjY3LC0xLjE5NyAyLjY2NywtMi42NjggMCwtMS40NyAtMS4xOTcsLTIuNjY2IC0yLjY2NywtMi42NjYgdiAwIDAgeiIKICAgICBpZD0icGF0aDM4MTQiCiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZiIKICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIiAvPgo8L3N2Zz4K" IdentifyModeActive = "" AudioMuteIcon = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdGVkIGJ5IEljb01vb24uaW8gLS0+Cgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHZlcnNpb249IjEuMSIKICAgd2lkdGg9IjMyIgogICBoZWlnaHQ9IjMyIgogICB2aWV3Qm94PSIwIDAgMzIgMzIiCiAgIGlkPSJzdmc2IgogICBzb2RpcG9kaTpkb2NuYW1lPSJhdWRpb2xldmVsLW11dGVkX3doaXRlLnN2ZyIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC45Mi41ICgyMDYwZWMxZjlmLCAyMDIwLTA0LTA4KSI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhMTIiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPmF1ZGlvbGV2ZWwtbXV0ZWQ8L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTAiIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSI3NzIiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iNDgwIgogICAgIGlkPSJuYW1lZHZpZXc4IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSI3LjM3NSIKICAgICBpbmtzY2FwZTpjeD0iMTYiCiAgICAgaW5rc2NhcGU6Y3k9IjE2IgogICAgIGlua3NjYXBlOndpbmRvdy14PSI0NSIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMzUiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmc2IiAvPgogIDx0aXRsZQogICAgIGlkPSJ0aXRsZTIiPmF1ZGlvbGV2ZWwtbXV0ZWQ8L3RpdGxlPgogIDxwYXRoCiAgICAgZD0iTTkuNDI1IDE5Ljk1M2gtMi4wMDh2LTcuOTA2aDUuNTQ2bDYuOTMzLTYuNTg4djQuMDIybC0xMC40NzIgMTAuNDcyek0xNC45MDggMjEuOGw0Ljk4OSA0Ljc0di05LjcyOWwtNC45ODkgNC45ODl6TTI1LjA2NiA2LjI5M2wxLjc2NSAxLjc2NS0xNy42NDggMTcuNjQ4LTEuNzY1LTEuNzY1IDE3LjY0OC0xNy42NDh6IgogICAgIGlkPSJwYXRoNCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmIiAvPgo8L3N2Zz4K" AudioUnmuteIcon = "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gR2VuZXJhdGVkIGJ5IEljb01vb24uaW8gLS0+Cgo8c3ZnCiAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgeG1sbnM6Y2M9Imh0dHA6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL25zIyIKICAgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHZlcnNpb249IjEuMSIKICAgd2lkdGg9IjMyIgogICBoZWlnaHQ9IjMyIgogICB2aWV3Qm94PSIwIDAgMzIgMzIiCiAgIGlkPSJzdmc2IgogICBzb2RpcG9kaTpkb2NuYW1lPSJhdWRpb2xldmVsX3doaXRlLnN2ZyIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC45Mi41ICgyMDYwZWMxZjlmLCAyMDIwLTA0LTA4KSI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhMTIiPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPmF1ZGlvbGV2ZWw8L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTAiIC8+CiAgPHNvZGlwb2RpOm5hbWVkdmlldwogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzY2NjY2NiIKICAgICBib3JkZXJvcGFjaXR5PSIxIgogICAgIG9iamVjdHRvbGVyYW5jZT0iMTAiCiAgICAgZ3JpZHRvbGVyYW5jZT0iMTAiCiAgICAgZ3VpZGV0b2xlcmFuY2U9IjEwIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwIgogICAgIGlua3NjYXBlOnBhZ2VzaGFkb3c9IjIiCiAgICAgaW5rc2NhcGU6d2luZG93LXdpZHRoPSI3NzIiCiAgICAgaW5rc2NhcGU6d2luZG93LWhlaWdodD0iNDgwIgogICAgIGlkPSJuYW1lZHZpZXc4IgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSI3LjM3NSIKICAgICBpbmtzY2FwZTpjeD0iMTYiCiAgICAgaW5rc2NhcGU6Y3k9IjE2IgogICAgIGlua3NjYXBlOndpbmRvdy14PSI0NSIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMzUiCiAgICAgaW5rc2NhcGU6d2luZG93LW1heGltaXplZD0iMCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJzdmc2IiAvPgogIDx0aXRsZQogICAgIGlkPSJ0aXRsZTIiPmF1ZGlvbGV2ZWw8L3RpdGxlPgogIDxwYXRoCiAgICAgZD0iTTguNjY3IDIwaDUuMzMzbDYuNjY3IDYuNjY3di0yMS4zMzNsLTYuNjY3IDYuNjY3aC01LjMzM3Y4eiIKICAgICBpZD0icGF0aDQiCiAgICAgc3R5bGU9ImZpbGw6I2ZmZmZmZiIgLz4KPC9zdmc+Cg==" --[[ getOrder ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Array: orderState Calls : Return : Purpose : Create a layering schema for z-order of objects on the GUI Notes : Intended to be used with small numbers i.e. 1-9 (1 is background 9 is foreground) ----------------------------------------------------------------------------------------------------------------- ]]-- local orderState = {} function getOrder(level) if orderState[level] then orderState[level] = orderState[level] + 1 return orderState[level] else orderState[level] = level*1000 return orderState[level] end end ----------------------------------------------------------------------------------------------------------------- --GetProperties ----------------------------------------------------------------------------------------------------------------- function GetProperties() props = {} table.insert(props, { -- Depending on the Model, there will be different controls exposed. Name = "Model", Type = "enum", Choices = {"TCCM"}, Value = "TCCM", -- This determines the 'default' value when the plugin is dragged into the design }) return props end ----------------------------------------------------------------------------------------------------------------- --GetModel ----------------------------------------------------------------------------------------------------------------- function GetModel(props) return props end ----------------------------------------------------------------------------------------------------------------- --GetPrettyName ----------------------------------------------------------------------------------------------------------------- function GetPrettyName( props ) return PluginInfo.Name .. "\r\nv" .. PluginInfo.Version end ----------------------------------------------------------------------------------------------------------------- -- ----------------------------------------------------------------------------------------------------------------- function RectifyProperties(props) return props end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --GetControls ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function GetControls(props) local ctrls = {} table.insert(ctrls, { Name = "Status", ControlType = "Indicator", IndicatorType = Reflect and "StatusGP" or "Status", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "IPAddress", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "Username", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "Password", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) ----------------------------------------------------------------------------------------------------------------- table.insert(ctrls, { Name = "DeviceType", ControlType = "Text", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceTypeIcon", ControlType = "Button", ButtonType = "Trigger", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceTypeColor", ControlType = "Button", ButtonType = "Trigger", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceSerial", ControlType = "Indicator", IndicatorType = "Text", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceFirmware", ControlType = "Indicator", IndicatorType = "Text", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceName", ControlType = "Indicator", IndicatorType = "Text", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceLocation", ControlType = "Indicator", IndicatorType = "Text", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "DeviceIdentify", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) ----------------------------------------------------------------------------------------------------------------- table.insert(ctrls, { Name = "SourceDetectionTracking", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "SourceVerticalValue", ControlType = "Knob", ControlUnit = "Integer", Min = 0, Max = 90, PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "SourceHorizontalValue", ControlType = "Knob", ControlUnit = "Integer", Min = 0, Max = 360, PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "PriorityZone", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "ExclusionZone1", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "ExclusionZone2", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "ExclusionZone3", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "ExclusionZone4", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "ExclusionZone5", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "LEDBrightness", ControlType = "Knob", ControlUnit = "Integer", Min = 0, Max = 5, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "LEDCustomColor", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "CustomColor", ControlType = "Text", ControlUnit = "ComboBox", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "MicOnColor", ControlType = "Text", ControlUnit = "ComboBox", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "MicMuteColor", ControlType = "Text", ControlUnit = "ComboBox", PinStyle = "Both", Count = 1, UserPin = true }) ----------------------------------------------------------------------------------------------------------------- table.insert(ctrls, { Name = "AudioLevelTracking", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioLevel", ControlType = "Indicator", IndicatorType = "Meter", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioLevelMuteIcon", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioMute", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "OutputLevelAnalog", ControlType = "Indicator", IndicatorType = "Meter", PinStyle = "Output", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "OutputLevelAnalogText", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel1", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel2", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel3", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel4", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel5", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel6", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel7", ControlType = "Knob", ControlUnit = "Integer", Min = -8, Max = 8, PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel1Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel2Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel3Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel4Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel5Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel6Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "AudioCustomEQLevel7Text", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "SensitivityThreshold", ControlType = "Text", PinStyle = "Both", Count = 1, UserPin = true }) table.insert(ctrls, { Name = "TruVoiceLift", ControlType = "Button", ButtonType = "Toggle", PinStyle = "Both", Count = 1, UserPin = true }) return ctrls end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --GetControlLayout ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- function GetControlLayout(props) local layout = {} local graphics = {} ----------------------------------------------------------------------------------------------------------------- --Header Bar ----------------------------------------------------------------------------------------------------------------- --Background table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Grey, CornerRadius = 1, StrokeWidth = 0, Position = {0, 0}, Size = {1280, 800}, ZOrder = getOrder(1) }) --top bar table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Black, CornerRadius = 1, StrokeWidth = 0, Position = {0, 0}, Size = {1280, 70}, ZOrder = getOrder(2) }) --Sennheiser Logo table.insert(graphics,{ Type = "Svg", Image = SennheiserLogo, Position = { 10, 5 }, Size = { 438, 59 }, ZOrder = getOrder(3) }) --top bar stroke line table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Blue, CornerRadius = 1, StrokeWidth = 0, Position = {0, 70}, Size = {1280, 3}, ZOrder = getOrder(2) }) ----------------------------------------------------------------------------------------------------------------- --Status Indicator layout["Status"] = { PrettyName = "System~Status", Style = "Text", Position = {870, 15}, Size = {200, 20}, FontSize = 12, TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Connection IP Address Text table.insert(graphics,{ Type = "Text", Text = "IP Address:", Font = "Roboto", FontSize = 12, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {870, 35}, Size = {100, 20}, ZOrder = getOrder(4) }) --Connection IP Address Input box layout["IPAddress"] = { PrettyName = "System~IP Address", Style = "Text", Position = {970, 35}, Size = {100, 20}, FontSize = 12, ZOrder = getOrder(4) } --Connection Username Text table.insert(graphics,{ Type = "Text", Text = "Username:", Font = "Roboto", FontSize = 12, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {1070, 15}, Size = {100, 20}, ZOrder = getOrder(4) }) --Connection Username Input box layout["Username"] = { PrettyName = "System~Username", Style = "Text", Position = {1170, 15}, Size = {100, 20}, FontSize = 12, ZOrder = getOrder(4) } --Connection Password Text table.insert(graphics,{ Type = "Text", Text = "Password:", Font = "Roboto", FontSize = 12, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {1070, 35}, Size = {100, 20}, ZOrder = getOrder(4) }) --Connection Password Input box layout["Password"] = { PrettyName = "System~Password", Style = "Text", Position = {1170, 35}, Size = {100, 20}, FontSize = 12, ZOrder = getOrder(4) } ----------------------------------------------------------------------------------------------------------------- --Device Details Box Header table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Black, CornerRadius = 1, StrokeWidth = 0, Position = {50, 86}, Size = {1180, 30}, ZOrder = getOrder(3) }) --Device Details Box table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.DarkGrey, CornerRadius = 1, StrokeWidth = 0, Position = {50, 116}, Size = {1180, 70}, ZOrder = getOrder(3) }) --Device Type Text table.insert(graphics,{ Type = "Text", Text = "DeviceType:", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {75, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Type Readout layout["DeviceType"] = { PrettyName = "Device~Type", Style = "Text", Position = {110, 145}, Size = {100, 20}, TextBoxStyle = "NoBackground", FontSize = 16, HTextAlign = "Left", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Device Type Icon layout["DeviceTypeIcon"] = { PrettyName = "Device~TypeIcon", Style = "Button", Position = {55, 125}, Size = {50, 50}, ButtonStyle = "Trigger", IsReadOnly = false, ZOrder = getOrder(5) } --Device Type Color layout["DeviceTypeColor"] = { PrettyName = "Device~TypeColo", Style = "Button", Position = {52, 122}, Size = {56, 56}, ButtonStyle = "Trigger", IsReadOnly = false, ZOrder = getOrder(4) } --Device Name Text table.insert(graphics,{ Type = "Text", Text = "DeviceName:", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {250, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Name Readout layout["DeviceName"] = { PrettyName = "Device~Name", Style = "Text", Position = {250, 145}, Size = {150, 20}, TextBoxStyle = "NoBackground", FontSize = 16, TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Device Location Text table.insert(graphics,{ Type = "Text", Text = "DeviceLocation:", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {425, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Location Readout layout["DeviceLocation"] = { PrettyName = "Device~Location", Style = "Text", Position = {425, 145}, Size = {150, 20}, TextBoxStyle = "NoBackground", FontSize = 16, TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Device Serial Text table.insert(graphics,{ Type = "Text", Text = "DeviceSerial:", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {600, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Serial Readout layout["DeviceSerial"] = { PrettyName = "Device~Serial", Style = "Text", Position = {600, 145}, Size = {150, 20}, TextBoxStyle = "NoBackground", FontSize = 16, TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Device Firmware Text table.insert(graphics,{ Type = "Text", Text = "DeviceFirmware", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {775, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Firmware Readout layout["DeviceFirmware"] = { PrettyName = "Device~Firmware", Style = "Text", Position = {775, 145}, Size = {150, 20}, TextBoxStyle = "NoBackground", FontSize = 16, TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Device Identity Text table.insert(graphics,{ Type = "Text", Text = "Identify", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {1110, 90}, Size = {150, 20}, ZOrder = getOrder(5) }) --Device Identity Button layout["DeviceIdentify"] = { PrettyName = "Device~Identify", Style = "Button", Position = {1165, 126}, Size = {50, 50}, ButtonStyle = "Toggle", IsReadOnly = false, ZOrder = getOrder(5) } ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --Zone & LED Details Box Header table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Black, CornerRadius = 1, StrokeWidth = 0, Position = {50, 196}, Size = {1180, 30}, ZOrder = getOrder(3) }) --Zone & LED Details Box table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.DarkGrey, CornerRadius = 1, StrokeWidth = 0, Position = {50, 226}, Size = {1180, 250}, ZOrder = getOrder(3) }) --Position Tracking Text table.insert(graphics,{ Type = "Text", Text = "Tracking", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {75, 230}, Size = {150, 20}, ZOrder = getOrder(5) }) --Position Tracking Button layout["SourceDetectionTracking"] = { PrettyName = "Zones~DetectionTracking", Style = "Button", Position = {75, 250}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Position Vertical Text table.insert(graphics,{ Type = "Text", Text = "Vertical Angle:", Font = "Roboto", FontSize = 14, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {75, 350}, Size = {150, 20}, ZOrder = getOrder(5) }) --Position Vertical Readout layout["SourceVerticalValue"] = { PrettyName = "Zones~Vertical Angle", Style = "Text", Position = {230, 350}, Size = {50, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Left", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Position Tracking Text table.insert(graphics,{ Type = "Text", Text = "Horizontal Angle:", Font = "Roboto", FontSize = 14, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {75, 390}, Size = {150, 20}, ZOrder = getOrder(5) }) --Position Tracking Readout layout["SourceHorizontalValue"] = { PrettyName = "Zones~Horizontal Angle", Style = "Text", Position = {230, 390}, Size = {50, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Left", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Priority Zone Text table.insert(graphics,{ Type = "Text", Text = "Priority Zone", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {250, 200}, Size = {150, 20}, ZOrder = getOrder(5) }) --Priority Zone Button layout["PriorityZone"] = { PrettyName = "Zones~Priority Zone", Style = "Button", Position = {250, 250}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Exlusion Zone Text table.insert(graphics,{ Type = "Text", Text = "Exlusion Zones", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {425, 200}, Size = {150, 20}, ZOrder = getOrder(5) }) --Exlusion Zone 1 Text table.insert(graphics,{ Type = "Text", Text = "Zone 1: ", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Right", VTextAlign = "Center", Color = Colors.White, Position = {440, 250}, Size = {60, 35}, ZOrder = getOrder(5) }) --Exlusion Zone 1 Button layout["ExclusionZone1"] = { PrettyName = "Zones~Exclusion Zone1", Style = "Button", Position = {500, 250}, Size = { 50, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Off", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Exlusion Zone 2 Text table.insert(graphics,{ Type = "Text", Text = "Zone 2: ", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Right", VTextAlign = "Center", Color = Colors.White, Position = {440, 295}, Size = {60, 35}, ZOrder = getOrder(5) }) --Exlusion Zone 2 Button layout["ExclusionZone2"] = { PrettyName = "Zones~Exclusion Zone2", Style = "Button", Position = {500, 295}, Size = { 50, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Off", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Exlusion Zone 3 Text table.insert(graphics,{ Type = "Text", Text = "Zone 3: ", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Right", VTextAlign = "Center", Color = Colors.White, Position = {440, 340}, Size = {60, 35}, ZOrder = getOrder(5) }) --Exlusion Zone 3 Button layout["ExclusionZone3"] = { PrettyName = "Zones~Exclusion Zone3", Style = "Button", Position = {500, 340}, Size = { 50, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Off", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Exlusion Zone 4 Text table.insert(graphics,{ Type = "Text", Text = "Zone 4: ", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Right", VTextAlign = "Center", Color = Colors.White, Position = {440, 385}, Size = {60, 35}, ZOrder = getOrder(5) }) --Exlusion Zone 4 Button layout["ExclusionZone4"] = { PrettyName = "Zones~Exclusion Zone4", Style = "Button", Position = {500, 385}, Size = { 50, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Off", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Exlusion Zone 5 Text table.insert(graphics,{ Type = "Text", Text = "Zone 5: ", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Right", VTextAlign = "Center", Color = Colors.White, Position = {440, 430}, Size = {60, 35}, ZOrder = getOrder(5) }) --Exlusion Zone 5 Button layout["ExclusionZone5"] = { PrettyName = "Zones~Exclusion Zone5", Style = "Button", Position = {500, 430}, Size = { 50, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Off", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --LED Brightness Text table.insert(graphics,{ Type = "Text", Text = "LED Brightness", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {600, 200}, Size = {150, 20}, ZOrder = getOrder(5) }) --LED Brightness Meter layout["LEDBrightness"] = { PrettyName = "LED~Brightness", Style = "Fader", Position = { 600, 250 }, Size = { 150, 20 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --LED Brightness Scale Text table.insert(graphics,{ Type = "Text", Text = "Off 1 2 3 4 5", Font = "Roboto", FontSize = 14, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {600, 270}, Size = {150, 20}, ZOrder = getOrder(5) }) --LED Custom Color Text table.insert(graphics,{ Type = "Text", Text = "Custom Color", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {910, 200}, Size = {150, 20}, ZOrder = getOrder(5) }) --LED Custom Color Button layout["LEDCustomColor"] = { PrettyName = "LED~Custom Color Button", Style = "Button", Position = {910, 250}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --LED Custom Text table.insert(graphics,{ Type = "Text", Text = "Custom", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {775, 310}, Size = {120, 20}, ZOrder = getOrder(5) }) --LED Custom Readout layout["CustomColor"] = { PrettyName = "LED~Custom Color", Position = { 775, 340 }, Size = { 120, 20 }, Style = "ComboBox", Color = Colors.DarkGrey, TextBoxStyle = "NoBackground", TextFontSize = 16, TextColor = Colors.White, HTextAlign = "Center", VTextAlign = "Center", WordWrap = true, IsBold = false, Margin = 0, Radius = 0, Padding = 2, IsReadOnly = false, ZOrder = getOrder(5), } --LED Mic On Color Text table.insert(graphics,{ Type = "Text", Text = "Mic On", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {925, 310}, Size = {120, 20}, ZOrder = getOrder(5) }) --LED Mic On Color Readout layout["MicOnColor"] = { PrettyName = "LED~Mic On Color", Position = { 925, 340 }, Size = { 120, 20 }, Style = "ComboBox", TextBoxStyle = "NoBackground", Color = Colors.DarkGrey, TextFontSize = 16, TextColor = Colors.White, HTextAlign = "Center", VTextAlign = "Center", WordWrap = true, IsBold = false, Margin = 0, Radius = 0, Padding = 2, IsReadOnly = false, ZOrder = getOrder(5), } --LED Mic Mute Color Text table.insert(graphics,{ Type = "Text", Text = "Mic Mute", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {1075, 310}, Size = {120, 20}, ZOrder = getOrder(5) }) --LED Mic Mute Color Readout layout["MicMuteColor"] = { PrettyName = "LED~Mic Mute Color", Position = { 1075, 340 }, Size = { 120, 20 }, Style = "ComboBox", TextBoxStyle = "NoBackground", Color = Colors.DarkGrey, TextFontSize = 16, TextColor = Colors.White, HTextAlign = "Cener", VTextAlign = "Center", WordWrap = true, IsBold = false, Margin = 0, Radius = 0, Padding = 2, IsReadOnly = false, ZOrder = getOrder(5), } ----------------------------------------------------------------------------------------------------------------- --Audio Details Box Header table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.Black, CornerRadius = 1, StrokeWidth = 0, Position = {50, 486}, Size = {1180, 30}, ZOrder = getOrder(3) }) --Audio Details Box table.insert(graphics,{ Type = "GroupBox", Text = "", HTextAlign = "Left", Fill = Colors.DarkGrey, CornerRadius = 1, StrokeWidth = 0, Position = {50, 516}, Size = {1180, 200}, ZOrder = getOrder(3) }) --Audio Level Text table.insert(graphics,{ Type = "Text", Text = "Audio Level", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {75, 490}, Size = {150, 20}, ZOrder = getOrder(5) }) --Audio Tracking Text table.insert(graphics,{ Type = "Text", Text = "Tracking", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {75, 520}, Size = {150, 20}, ZOrder = getOrder(5) }) --Audio Tracking Button layout["AudioLevelTracking"] = { PrettyName = "Audio~LevelTracking", Style = "Button", Position = {75, 540}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Audio Level Meter layout["AudioLevel"] = { PrettyName = "Audio~Level", Position = { 105, 595 }, Size = { 120, 20 }, Color = Colors.PowderBlue, BackgroundColor = Colors.Grey, Margin = 0, Radius = 0, StrokeWidth = 0, Style = "Meter", MeterStyle = "Level", ShowTextbox = false, IsReadOnly = true, ZOrder = getOrder(5), } --Audio Mute Text table.insert(graphics,{ Type = "Text", Text = "Mute", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {75, 635}, Size = {150, 20}, ZOrder = getOrder(5) }) --Audio Mute Icon layout["AudioLevelMuteIcon"] = { PrettyName = "Audio~MuteIcon", Style = "Button", Position = {75, 590}, Size = {30, 30}, ButtonStyle = "Toggle", IsReadOnly = false, ZOrder = getOrder(5) } --Audio Mute button layout["AudioMute"] = { PrettyName = "Audio~Mute Button", Style = "Button", Position = {75, 670}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } --Audio Output Text table.insert(graphics,{ Type = "Text", Text = "Output Level (analog)", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {250, 490}, Size = {200, 20}, ZOrder = getOrder(5) }) --Audio Output range Text table.insert(graphics,{ Type = "Text", Text = "-18", Font = "Roboto", FontSize = 14, FontStyle = "Bold", HTextAlign = "Left", Color = Colors.White, Position = {280, 560}, Size = {30, 20}, ZOrder = getOrder(5) }) --Audio Output range Text table.insert(graphics,{ Type = "Text", Text = "0", Font = "Roboto", FontSize = 14, FontStyle = "Bold", HTextAlign = "Right", Color = Colors.White, Position = {400, 560}, Size = {30, 20}, ZOrder = getOrder(5) }) --Audio Output Meter layout["OutputLevelAnalog"] = { PrettyName = "Audio~OutputLevelAnalog", Position = { 280, 540 }, Size = { 150, 20 }, Color = Colors.PowderBlue, BackgroundColor = Colors.Grey, Margin = 0, Radius = 0, StrokeWidth = 0, Style = "Meter", MeterStyle = "Level", ShowTextbox = false, IsReadOnly = true, ZOrder = getOrder(5), } --Audio Output dB Text layout["OutputLevelAnalogText"] = { PrettyName = "Audio~OutputLevelAnalogText", Style = "Text", Position = {325, 560}, Size = {60, 20}, TextBoxStyle = "NoBackground", FontSize = 16, HTextAlign = "Right", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Sound Profile Text table.insert(graphics,{ Type = "Text", Text = "Sound Profile", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {700, 490}, Size = {150, 20}, ZOrder = getOrder(5) }) --Audio EQ 1 Text table.insert(graphics,{ Type = "Text", Text = "125", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {700, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 1 Fader layout["AudioCustomEQLevel1"] = { PrettyName = "Audio~CustomLevel1", Style = "Fader", Position = { 700, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 1 Readout layout["AudioCustomEQLevel1Text"] = { PrettyName = "Audio~CustomLevel1Text", Style = "Text", Position = {700, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 2 Text table.insert(graphics,{ Type = "Text", Text = "250", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {722, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 2 Fader layout["AudioCustomEQLevel2"] = { PrettyName = "Audio~CustomLevel2", Style = "Fader", Position = { 722, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 2 Readout layout["AudioCustomEQLevel2Text"] = { PrettyName = "Audio~CustomLevel2Text", Style = "Text", Position = {722, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 3 Text table.insert(graphics,{ Type = "Text", Text = "500", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {744, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 3 Fader layout["AudioCustomEQLevel3"] = { PrettyName = "Audio~CustomLevel3", Style = "Fader", Position = { 744, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 3 Readout layout["AudioCustomEQLevel3Text"] = { PrettyName = "Audio~CustomLevel3Text", Style = "Text", Position = {744, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 4 Text table.insert(graphics,{ Type = "Text", Text = "1K", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {766, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 4 Fader layout["AudioCustomEQLevel4"] = { PrettyName = "Audio~CustomLevel4", Style = "Fader", Position = { 766, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 4 Readout layout["AudioCustomEQLevel4Text"] = { PrettyName = "Audio~CustomLevel4Text", Style = "Text", Position = {766, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 5 Text table.insert(graphics,{ Type = "Text", Text = "2K", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {788, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 5 Fader layout["AudioCustomEQLevel5"] = { PrettyName = "Audio~CustomLevel5", Style = "Fader", Position = { 788, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 5 Readout layout["AudioCustomEQLevel5Text"] = { PrettyName = "Audio~CustomLevel5Text", Style = "Text", Position = {788, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 6 Text table.insert(graphics,{ Type = "Text", Text = "4K", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {810, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 6 Fader layout["AudioCustomEQLevel6"] = { PrettyName = "Audio~CustomLevel6", Style = "Fader", Position = { 810, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 6 Readout layout["AudioCustomEQLevel6Text"] = { PrettyName = "Audio~CustomLevel6Text", Style = "Text", Position = {810, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio EQ 7 Text table.insert(graphics,{ Type = "Text", Text = "8K", Font = "Roboto", FontSize = 8, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {832, 660}, Size = {20, 20}, ZOrder = getOrder(5) }) --Audio EQ 7 Fader layout["AudioCustomEQLevel7"] = { PrettyName = "Audio~CustomLevel7", Style = "Fader", Position = { 832, 560 }, Size = { 20, 100 }, Color = Colors.PowderBlue, IsReadOnly = false, ZOrder = getOrder(5), } --Audio EQ 7 Readout layout["AudioCustomEQLevel7Text"] = { PrettyName = "Audio~CustomLevel7Text", Style = "Text", Position = {832, 540}, Size = {20, 20}, TextBoxStyle = "NoBackground", FontSize = 12, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Sensitivity Threshold Text table.insert(graphics,{ Type = "Text", Text = "Sensitivity Threshold", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {850, 490}, Size = {200, 20}, ZOrder = getOrder(5) }) --Sensitivity Threshold Readout layout["SensitivityThreshold"] = { PrettyName = "Audio~SensitivityThreshold", Style = "Text", Position = {875, 540}, Size = {150, 35}, TextBoxStyle = "NoBackground", FontSize = 16, HTextAlign = "Center", TextColor = Colors.White, UnlinkTextColor = true, ZOrder = getOrder(5) } --Audio TruVoiceLift Text table.insert(graphics,{ Type = "Text", Text = "TruVoiceLift", Font = "Roboto", FontSize = 16, FontStyle = "Bold", HTextAlign = "Center", Color = Colors.White, Position = {1050, 490}, Size = {150, 20}, ZOrder = getOrder(5) }) --Audio TruVoiceLift Button layout["TruVoiceLift"] = { PrettyName = "Audio~TruVoiceLift", Style = "Button", Position = {1050, 540}, Size = { 150, 35 }, Color = Colors.PowderBlue, Style = "Button", ButtonStyle = "Toggle", Legend = "Deactivated", TextFontSize = 16, HTextAlign = "Center", VTextAlign = "Center", UnlinkOffColor = true, OffColor = Colors.Grey, Margin = 2, Radius = 5, StrokeWidth = 1, IsReadOnly = false, ZOrder = getOrder(5), } return layout, graphics end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --Main code ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- if Controls then ----------------------------------------------------------------------------------------------------------------- --Required objects ----------------------------------------------------------------------------------------------------------------- json = require("rapidjson") ----------------------------------------------------------------------------------------------------------------- -- Control Aliases ----------------------------------------------------------------------------------------------------------------- Status = Controls.Status IPAddress = Controls.IPAddress Username = Controls.Username Password = Controls.Password ----------------------------------------------------------------------------------------------------------------- DeviceName = Controls.DeviceName DeviceType = Controls.DeviceType DeviceTypeIcon = Controls.DeviceTypeIcon DeviceTypeColor = Controls.DeviceTypeColor DeviceSerial = Controls.DeviceSerial DeviceFirmware = Controls.DeviceFirmware DeviceLocation = Controls.DeviceLocation DeviceIdentify = Controls.DeviceIdentify ----------------------------------------------------------------------------------------------------------------- SourceDetectionTracking = Controls.SourceDetectionTracking SourceVerticalValue = Controls.SourceVerticalValue SourceHorizontalValue = Controls.SourceHorizontalValue PriorityZone = Controls.PriorityZone ExclusionZone1 = Controls.ExclusionZone1 ExclusionZone2 = Controls.ExclusionZone2 ExclusionZone3 = Controls.ExclusionZone3 ExclusionZone4 = Controls.ExclusionZone4 ExclusionZone5 = Controls.ExclusionZone5 LEDBrightness = Controls.LEDBrightness LEDCustomColor = Controls.LEDCustomColor MicOnColor = Controls.MicOnColor MicMuteColor = Controls.MicMuteColor CustomColor = Controls.CustomColor ----------------------------------------------------------------------------------------------------------------- AudioLevelTracking = Controls.AudioLevelTracking AudioLevel = Controls.AudioLevel AudioLevelMuteIcon = Controls.AudioLevelMuteIcon AudioMute = Controls.AudioMute OutputLevelAnalog = Controls.OutputLevelAnalog OutputLevelAnalogText = Controls.OutputLevelAnalogText AudioCustomEQLevel1 = Controls.AudioCustomEQLevel1 AudioCustomEQLevel2 = Controls.AudioCustomEQLevel2 AudioCustomEQLevel3 = Controls.AudioCustomEQLevel3 AudioCustomEQLevel4 = Controls.AudioCustomEQLevel4 AudioCustomEQLevel5 = Controls.AudioCustomEQLevel5 AudioCustomEQLevel6 = Controls.AudioCustomEQLevel6 AudioCustomEQLevel7 = Controls.AudioCustomEQLevel7 AudioCustomEQLevel1Text = Controls.AudioCustomEQLevel1Text AudioCustomEQLevel2Text = Controls.AudioCustomEQLevel2Text AudioCustomEQLevel3Text = Controls.AudioCustomEQLevel3Text AudioCustomEQLevel4Text = Controls.AudioCustomEQLevel4Text AudioCustomEQLevel5Text = Controls.AudioCustomEQLevel5Text AudioCustomEQLevel6Text = Controls.AudioCustomEQLevel6Text AudioCustomEQLevel7Text = Controls.AudioCustomEQLevel7Text SensitivityThreshold = Controls.SensitivityThreshold TruVoiceLift = Controls.TruVoiceLift ----------------------------------------------------------------------------------------------------------------- -- Global Variables ----------------------------------------------------------------------------------------------------------------- AuthHash = "" nPollCounter = 0 gnHeartbeat = 0 nHeartbeatCounter = 0 gnSubCommandListCount = 0 nIdentifyStatus = false nPositionTracking = false nAudioTracking = false arrNoiseLevelOptions = {[1]="Quiet", [2]="Normal", [3]="Loud",} arrColorOptions = {[1]="Green", [2]="Blue", [3]="Red", [4]="Yellow", [5]="Orange", [6]="Cyan", [7]="Pink",} arrInternal = {} arrExlusionZones = {false, false, false, false, false} arrAudioCustomEQLevels = {0,0,0,0,0,0,0} StatusState = {OK=0, COMPROMISED=1, FAULT=2, NOTPRESENT=3, MISSING=4, INITIALIZING=5} -- Status states in designer ----------------------------------------------------------------------------------------------------------------- --[[ ReportStatus ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Online Calls : Return : Purpose : Displays Status of the online conneciton Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function ReportStatus(state,msg) local msg = msg or "" Status.Value = StatusState[state] -- Sets status state Status.String = msg -- Sets status message end ----------------------------------------------------------------------------------------------------------------- --[[ Init ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Calls : Return : Purpose : Function to Initialize Runtime Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function Init() print("Init") ReportStatus("INITIALIZING", "Initializing") fnInitPoll() end ----------------------------------------------------------------------------------------------------------------- --[[ Create and setup Polling ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Calls : fnInitPoll, fnPoll, fnSend Return : Purpose : Create a timer to poll the extended info of device Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- --Create Timer timerPoll = Timer.New() --When event is called, start poll cycle timerPoll.EventHandler = function(timer) fnPoll() end --refresh polling function fnInitPoll() nPollCounter = 0 timerPoll:Stop() timerPoll:Start(1) end -- list of items to poll function fnPoll() nPollCounter = nPollCounter + 1 if nPollCounter == 1 then fnSendGetCommand(apiDeviceSite, parseDeviceSiteData) elseif nPollCounter == 4 then fnSendGetCommand(apiDeviceIdentity, parseDeviceIdentityData) elseif nPollCounter == 7 then fnSendGetCommand(apiFirmwareUpdateState, parseDeviceFirmwareData) elseif nPollCounter == 10 then fnSendGetCommand(apiDeviceIdentification, parseDeviceIdentificationData) elseif nPollCounter == 13 then fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) elseif nPollCounter == 16 then fnSendGetCommand(apiAudioOutputsLevel, parseAudioOutputsLevelData) elseif nPollCounter == 19 then fnSendGetCommand(apiAudioMute, parseAudioMuteData) elseif nPollCounter == 22 then fnSendGetCommand(apiAudioEqualizer, parseAudioEqualizerData) elseif nPollCounter == 25 then fnSendGetCommand(apiAudioVoiceLift, parseAudioVoiceLiftData) elseif nPollCounter == 28 then fnSendGetCommand(apiAudioInputMicSensitivity, parseAudioInputMicSensitivityData) elseif nPollCounter == 31 then arrInternal = {} arrExlusionZones = {} fnSendGetCommand(apiAudioInputMicExclusionZones, parseAudioInputMicExclusionZonesData) elseif nPollCounter == 34 then fnSendGetCommand(apiAudioInputMicPriorityZones, parseAudioInputMicPriorityZonesData) elseif nPollCounter == 2 or nPollCounter == 5 or nPollCounter == 8 or nPollCounter == 11 or nPollCounter == 14 or nPollCounter == 17 or nPollCounter == 20 or nPollCounter == 23 or nPollCounter == 26 or nPollCounter == 29 or nPollCounter == 32 then --If the audio tracking is disabled, dont send the get command for audio level if nAudioTracking then fnSendGetCommand(apiAudioInputsMicLevel, parseAudioInputsMicLevelData) end elseif nPollCounter == 3 or nPollCounter == 6 or nPollCounter == 9 or nPollCounter == 12 or nPollCounter == 15 or nPollCounter == 18 or nPollCounter == 21 or nPollCounter == 24 or nPollCounter == 27 or nPollCounter == 30 or nPollCounter == 33 then --If the position tracking is disabled, dont send the subscribe command for elevation if nPositionTracking then fnSendGetCommand(apiAudioInputMicBeam, parseAudioInputMicBeamData) end elseif nPollCounter > 35 then nPollCounter = 0 end end ----------------------------------------------------------------------------------------------------------------- --[[ fnHeartbeatStatus ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Calls : Return : Purpose : Function to track the communication via a heartbeat Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function fnHeartbeatStatus(value) if(value == 0) then gnHeartbeat = 0 ReportStatus("OK", "") else gnHeartbeat = gnHeartbeat + value end print("-->gnHeartbeat: " .. gnHeartbeat) if(gnHeartbeat >= 5) then ReportStatus("FAULT", "Lost response from heartbeat") end end ----------------------------------------------------------------------------------------------------------------- --[[ fnSendGetCommand ----------------------------------------------------------------------------------------------------------------- Arguments: cmd = the command to issue callback = the function that will parse the data Output : Globals : Calls : fnHeartbeatStatus = add a counter to the heartbeat to track for communication. Return : Purpose : Function to send a GET command to the device Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function fnSendGetCommand(cmd, callback) AuthHash = Username.String..":"..Password.String HttpClient.Download { Url = "https://"..IPAddress.String..":443"..cmd, Headers = { ["Content-Type"] = "application/json", ["Authorization"] = "Basic "..Crypto.Base64Encode(AuthHash), ["Accept"] = "*/*" }, Timeout = 30, EventHandler = callback } fnHeartbeatStatus(1) end ----------------------------------------------------------------------------------------------------------------- --[[ fnSendPutCommand ----------------------------------------------------------------------------------------------------------------- Arguments: cmd = the command to issue callback = the function that will parse the data Output : Globals : Calls : fnHeartbeatStatus = add a counter to the heartbeat to track for communication. Return : Purpose : Function to send a GET command to the device Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function fnSendPutCommand(cmd, body, callback) print("cmd:", cmd) print("body:", body) AuthHash = Username.String..":"..Password.String HttpClient.Upload { Url = "https://"..IPAddress.String..":443"..cmd, Method = "PUT", Headers = { ["Content-Type"] = "application/json", ["Authorization"] = "Basic "..Crypto.Base64Encode(AuthHash), ["Accept"] = "*/*" }, Timeout = 30, Data = body, EventHandler = callback } fnHeartbeatStatus(1) end ----------------------------------------------------------------------------------------------------------------- --[[ parsePUTData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Globals : Calls : fnHeartbeatStatus Return : Purpose : receives data from the PUT request Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parsePUTData(tbl, code, data, err, headers) print(string.format("[parsePUTData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parsePUTData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parsePUTData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) else fnHeartbeatStatus(0) end end ----------------------------------------------------------------------------------------------------------------- --[[ parseJSON ----------------------------------------------------------------------------------------------------------------- Arguments: t = json table data match = the match string to look for Output : Globals : Calls : parseJSON (recursive for tables within the table) Return : matched value Purpose : Recursive function to sort through the JSON data Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseJSON(t, match) for k,v in pairs(t) do --print("k",k) --print("v",v) if k == match then --print("match:", v) return v elseif type(v) == "table" then --print("table v",v) parseJSON(v, match) end end end ----------------------------------------------------------------------------------------------------------------- --[[ parseJSONList ----------------------------------------------------------------------------------------------------------------- Arguments: t = json table data match = the match string to look for Output : Globals : Calls : parseJSON (recursive for tables within the table) Return : matched value Purpose : Recursive function to sort through the JSON data Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseJSONList(t, match) for k,v in pairs(t) do --print("k",k) --print("v",v) if type(v) == "table" then --print("table",v) parseJSONList(v, match) elseif k == match then print("match:", v) table.insert(arrInternal, v) end end return arrInternal end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --Functions for parsing incomming data ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --[[ Device ~parseDeviceSiteData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceName.String Controls.DeviceLocation.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : receives data from the GET request and parses the JSOn looking for a match Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseDeviceSiteData(tbl, code, data, err, headers) print(string.format("[parseDeviceSiteData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseDeviceSiteData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseDeviceSiteData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) else fnHeartbeatStatus(0) Controls.DeviceName.String = parseJSON(json.decode(data), "deviceName") Controls.DeviceLocation.String = parseJSON(json.decode(data), "location") end end ----------------------------------------------------------------------------------------------------------------- --[[ Device ~ParseDeviceIdentityData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceSerial.String Controls.DeviceType.String Controls.DeviceTypeIcon.Legend Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseDeviceIdentityData(tbl, code, data, err, headers) print(string.format("[parseDeviceIdentityData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseDeviceIdentityData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseDeviceIdentityData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) else fnHeartbeatStatus(0) Controls.DeviceSerial.String = parseJSON(json.decode(data), "serial") Controls.DeviceType.String = parseJSON(json.decode(data), "product") local icon = { DrawChrome = false, -- Draw the button face and edges IconData = TCCMIcon, } Controls.DeviceTypeIcon.Legend = json.encode(icon) end end ----------------------------------------------------------------------------------------------------------------- --[[ Device ~ParseDeviceFirmwareData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseDeviceFirmwareData(tbl, code, data, err, headers) print(string.format("[parseDeviceFirmwareData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseDeviceFirmwareData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseDeviceFirmwareData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) else fnHeartbeatStatus(0) Controls.DeviceFirmware.String = parseJSON(json.decode(data), "deviceVersion") end end ----------------------------------------------------------------------------------------------------------------- --[[ Device_Identify ----------------------------------------------------------------------------------------------------------------- Arguments: Output : DeviceIdentify.Value Globals : Calls : fnSend, fnIdentifyState, fnIdentifyBlink Return : Purpose : Parse Device Identify mode. (aka set or unset the Identify mode of the device), controls on/off state of identify button Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.DeviceIdentify.EventHandler = function() if nIdentifyStatus then fnSendPutCommand(apiDeviceIdentification, IdentifyReset, parsePUTData) else fnSendPutCommand(apiDeviceIdentification, IdentifySet, parsePUTData) end Timer.CallAfter(getIdentifyState, 1) Timer.CallAfter(getIdentifyState, 12) end function getIdentifyState() fnSendGetCommand(apiDeviceIdentification, parseDeviceIdentificationData) end ----------------------------------------------------------------------------------------------------------------- function fnIdentifyState(state) if state then Controls.DeviceIdentify.Value = 1 timerIdentify:Stop() timerIdentify:Start(1) else timerIdentify:Stop() local icon = { DrawChrome = false, -- Draw the button face and edges IconData = IdentifyModeInactive, } Controls.DeviceIdentify.Legend = json.encode(icon) end end --Identify Timer timerIdentify = Timer.New() --When event is called, start poll cycle timerIdentify.EventHandler = function(timer) fnIdentifyBlink() end -- list of items to poll function fnIdentifyBlink() local IdentifyIcon = IdentifyModeInactive if Controls.DeviceIdentify.Value == 1 then Controls.DeviceIdentify.Value = 0 IdentifyIcon = IdentifyModeActive nIdentifyStatus = true else Controls.DeviceIdentify.Value = 1 IdentifyIcon = IdentifyModeInactive nIdentifyStatus = false end local icon = { DrawChrome = false, -- Draw the button face and edges IconData = IdentifyIcon, } Controls.DeviceIdentify.Legend = json.encode(icon) end ----------------------------------------------------------------------------------------------------------------- --[[ Device ~parseDeviceIdentificationData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseDeviceIdentificationData(tbl, code, data, err, headers) print(string.format("[parseDeviceIdentificationData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseDeviceIdentificationData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseDeviceIdentificationData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) fnIdentifyState(false) else fnHeartbeatStatus(0) fnIdentifyState(parseJSON(json.decode(data), "visual")) end end ----------------------------------------------------------------------------------------------------------------- --Position and LED ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --[[ Position Tracking ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Calls : Return : Purpose : Set Position Tracking on/off Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.SourceDetectionTracking.EventHandler = function() if nPositionTracking then nPositionTracking = false Controls.SourceDetectionTracking.Legend = "Deactivated" else nPositionTracking = true Controls.SourceDetectionTracking.Legend = "Activated" fnSendGetCommand(apiAudioInputMicBeam, parseAudioInputMicBeamData) end Controls.SourceDetectionTracking.Value = nPositionTracking end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioInputMicBeamData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioInputMicBeamData(tbl, code, data, err, headers) print(string.format("[parseAudioInputMicBeamData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioInputMicBeamData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioInputMicBeamData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.SourceHorizontalValue.Value = 0 Controls.SourceVerticalValue.Value = 0 else fnHeartbeatStatus(0) Controls.SourceHorizontalValue.Value = parseJSON(json.decode(data), "azimuth") Controls.SourceVerticalValue.Value = parseJSON(json.decode(data), "elevation") end end ----------------------------------------------------------------------------------------------------------------- --[[ Priority Zone ----------------------------------------------------------------------------------------------------------------- Arguments: Output : PriorityZone.Boolean Globals : Calls : fnSend Return : Purpose : Set Priority Zone on/off Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.PriorityZone.EventHandler = function() local body if PriorityZone.Boolean then body = '{"enabled":true}' else body = '{"enabled":false}' end fnSendPutCommand(apiAudioInputMicPriorityZones, body, parsePUTData) Timer.CallAfter(updatePriorityZonesDelay, 2) end function updatePriorityZonesDelay() fnSendGetCommand(apiAudioInputMicPriorityZones, parseAudioInputMicPriorityZonesData) end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioInputMicPriorityZonesData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioInputMicPriorityZonesData(tbl, code, data, err, headers) print(string.format("[parseAudioInputMicPriorityZonesData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioInputMicPriorityZonesData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioInputMicPriorityZonesData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.PriorityZone.Boolean = false else fnHeartbeatStatus(0) Controls.PriorityZone.Boolean = parseJSON(json.decode(data), "enabled") if Controls.PriorityZone.Boolean then Controls.PriorityZone.Legend = "Activated" else Controls.PriorityZone.Legend = "Deactivated" end end end ----------------------------------------------------------------------------------------------------------------- --[[ fnExclusionCommand ----------------------------------------------------------------------------------------------------------------- Arguments: Output : Globals : Calls : fnSend Return : Purpose : Create and send Exclusion Zone Command Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function fnExclusionCommand(zone, state) local command = apiAudioInputMicExclusionZones.."/"..zone local body = '{"enabled":'.. tostring(state)..'}' fnSendPutCommand(command, body, parsePUTData) Timer.CallAfter(updateExclusionZonesDelay, 2) end function updateExclusionZonesDelay() fnSendGetCommand(apiAudioInputMicExclusionZones, parseAudioInputMicExclusionZonesData) end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioInputMicExclusionZonesData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioInputMicExclusionZonesData(tbl, code, data, err, headers) print(string.format("[parseAudioInputMicExclusionZonesData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioInputMicExclusionZonesData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioInputMicExclusionZonesData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.ExclusionZone1.Boolean = false Controls.ExclusionZone2.Boolean = false Controls.ExclusionZone3.Boolean = false Controls.ExclusionZone4.Boolean = false Controls.ExclusionZone5.Boolean = false arrExlusionZones = {false, false, false, false, false} else fnHeartbeatStatus(0) arrExlusionZones = parseJSONList(json.decode(data), "enabled") Controls.ExclusionZone1.Boolean = arrExlusionZones[1] Controls.ExclusionZone2.Boolean = arrExlusionZones[2] Controls.ExclusionZone3.Boolean = arrExlusionZones[3] Controls.ExclusionZone4.Boolean = arrExlusionZones[4] Controls.ExclusionZone5.Boolean = arrExlusionZones[5] if ExclusionZone1.Boolean then Controls.ExclusionZone1.Legend = "On" else Controls.ExclusionZone1.Legend = "Off" end if ExclusionZone2.Boolean then Controls.ExclusionZone2.Legend = "On" else Controls.ExclusionZone2.Legend = "Off" end if ExclusionZone3.Boolean then Controls.ExclusionZone3.Legend = "On" else Controls.ExclusionZone3.Legend = "Off" end if ExclusionZone4.Boolean then Controls.ExclusionZone4.Legend = "On" else Controls.ExclusionZone4.Legend = "Off" end if ExclusionZone5.Boolean then Controls.ExclusionZone5.Legend = "On" else Controls.ExclusionZone5.Legend = "Off" end end end ----------------------------------------------------------------------------------------------------------------- --[[ Exclusion Zone 1~5 ----------------------------------------------------------------------------------------------------------------- Arguments: Output : ExclusionZone.Boolean Globals : arrExlusionZones Calls : fnSend Return : Purpose : Set te value in the array to be used for sending a command Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.ExclusionZone1.EventHandler = function() if Controls.ExclusionZone1.Boolean then arrExlusionZones[1] = true else arrExlusionZones[1] = false end fnExclusionCommand(0, arrExlusionZones[1]) end ----------------------------------------------------------------------------------------------------------------- --Exclusion Zone 2 ----------------------------------------------------------------------------------------------------------------- Controls.ExclusionZone2.EventHandler = function() if Controls.ExclusionZone2.Boolean then arrExlusionZones[2] = true else arrExlusionZones[2] = false end fnExclusionCommand(1, arrExlusionZones[2]) end ----------------------------------------------------------------------------------------------------------------- --Exclusion Zone 3 ----------------------------------------------------------------------------------------------------------------- Controls.ExclusionZone3.EventHandler = function() if Controls.ExclusionZone3.Boolean then arrExlusionZones[3] = true else arrExlusionZones[3] = false end fnExclusionCommand(2, arrExlusionZones[3]) end ----------------------------------------------------------------------------------------------------------------- --Exclusion Zone 4 ----------------------------------------------------------------------------------------------------------------- Controls.ExclusionZone4.EventHandler = function() if Controls.ExclusionZone4.Boolean then arrExlusionZones[4] = true else arrExlusionZones[4] = false end fnExclusionCommand(3, arrExlusionZones[4]) end ----------------------------------------------------------------------------------------------------------------- --Exclusion Zone 5 ----------------------------------------------------------------------------------------------------------------- Controls.ExclusionZone5.EventHandler = function() if Controls.ExclusionZone5.Boolean then arrExlusionZones[5] = true else arrExlusionZones[5] = false end fnExclusionCommand(4, arrExlusionZones[5]) end ----------------------------------------------------------------------------------------------------------------- --[[ LED Brightness ----------------------------------------------------------------------------------------------------------------- Arguments: Output : LEDBrightness.Value Globals : Calls : fnSend Return : Purpose : Set and parse LED Brightness data Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.LEDBrightness.EventHandler = function() local body = '{"brightness":'..math.floor(Controls.LEDBrightness.Value)..'}' fnSendPutCommand(apiDeviceLED, body, parsePUTData) Timer.CallAfter(updateLEDBrightnessDelay, 2) end function updateLEDBrightnessDelay() fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) end ----------------------------------------------------------------------------------------------------------------- --[[ Device ~parseDeviceLEDData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceName.String Controls.DeviceLocation.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : receives data from the GET request and parses the JSOn looking for a match Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseDeviceLEDData(tbl, code, data, err, headers) print(string.format("[parseDeviceLEDData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseDeviceLEDData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseDeviceLEDData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.LEDBrightness.Value = 0 Controls.LEDCustomColor.Boolean = false Controls.CustomColor.String = "" Controls.MicOnColor.String = "" Controls.MicMuteColor.String = "" else fnHeartbeatStatus(0) Controls.LEDBrightness.Value = parseJSON(json.decode(data), "brightness") local micCustomTable = parseJSON(json.decode(data), "micCustom") Controls.LEDCustomColor.Boolean = parseJSON(micCustomTable, "enabled") Controls.CustomColor.String = parseJSON(micCustomTable, "color") local micOnTable = parseJSON(json.decode(data), "micOn") Controls.MicOnColor.String = parseJSON(micOnTable, "color") local micMuteTable = parseJSON(json.decode(data), "micMute") Controls.MicMuteColor.String = parseJSON(micMuteTable, "color") end if Controls.LEDCustomColor.Boolean then Controls.LEDCustomColor.Legend = "Activated" else Controls.LEDCustomColor.Legend = "Deactivated" end end ----------------------------------------------------------------------------------------------------------------- --[[ LED Custom Color ----------------------------------------------------------------------------------------------------------------- Arguments: Output : LEDCustomColor.Boolean Globals : Calls : fnSend Return : Purpose : Set and parse LED Custom Color data Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.LEDCustomColor.EventHandler = function() local body if Controls.LEDCustomColor.Boolean then body = '{"micCustom":{"enabled":true}}' else body = '{"micCustom":{"enabled":false}}' end fnSendPutCommand(apiDeviceLED, body, parsePUTData) Timer.CallAfter(updateLEDCustomDelay, 2) end function updateLEDCustomDelay() fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) end ----------------------------------------------------------------------------------------------------------------- --[[ Custom Color ----------------------------------------------------------------------------------------------------------------- Arguments: Output : CustomColor.String Globals : Calls : fnSend Return : Purpose : Set and parse feedback for Custom Color Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.CustomColor.EventHandler = function(ctl) local body = '{"micCustom":{"color":"'..ctl.String..'"}}' fnSendPutCommand(apiDeviceLED, body, parsePUTData) Timer.CallAfter(updateCustomColorDelay, 2) end function updateCustomColorDelay() fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) end ----------------------------------------------------------------------------------------------------------------- --[[ Mic On Color ----------------------------------------------------------------------------------------------------------------- Arguments: Output : MicOnColor.String Globals : Calls : fnSend Return : Purpose : Set and parse feedback for Mic On Color Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.MicOnColor.EventHandler = function(ctl) local body = '{"micOn":{"color":"'..ctl.String..'"}}' fnSendPutCommand(apiDeviceLED, body, parsePUTData) Timer.CallAfter(updateMicOnColorDelay, 2) end function updateMicOnColorDelay() fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) end ----------------------------------------------------------------------------------------------------------------- --[[ Mic Mute Color ----------------------------------------------------------------------------------------------------------------- Arguments: Output : MicMuteColor.String Globals : Calls : fnSend Return : Purpose : Set and parse feedback for Mic Mute Color Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.MicMuteColor.EventHandler = function(ctl) local body = '{"micMute":{"color":"'..ctl.String..'"}}' fnSendPutCommand(apiDeviceLED, body, parsePUTData) Timer.CallAfter(updateMicMuteColorDelay, 2) end function updateMicMuteColorDelay() fnSendGetCommand(apiDeviceLED, parseDeviceLEDData) end ----------------------------------------------------------------------------------------------------------------- --Audio ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --[[ Audo Level Tracking ----------------------------------------------------------------------------------------------------------------- Arguments: Output : AudioLevelTracking.Legend Globals : Calls : fnSend Return : Purpose : Set the tracking state of audio level to on/off Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.AudioLevelTracking.EventHandler = function() if nAudioTracking then nAudioTracking = false Controls.AudioLevelTracking.Legend = "Deactivated" else nAudioTracking = true Controls.AudioLevelTracking.Legend = "Activated" end Controls.AudioLevelTracking.Value = nAudioTracking end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioInputsMicLevelData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioInputsMicLevelData(tbl, code, data, err, headers) print(string.format("[parseAudioInputsMicLevelData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioInputsMicLevelData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioInputsMicLevelData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.AudioLevel.Value = -90 else fnHeartbeatStatus(0) Controls.AudioLevel.Value = parseJSON(json.decode(data), "peak") end end ----------------------------------------------------------------------------------------------------------------- --[[ Audo Mute ----------------------------------------------------------------------------------------------------------------- Arguments: Output : AudioMute.Boolean Globals : Calls : fnSend Return : Purpose : Set the Audo Mute state to on/off Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.AudioMute.EventHandler = function() local body if Controls.AudioMute.Boolean then body = '{"enabled":true}' else body = '{"enabled":false}' end fnSendPutCommand(apiAudioMute, body, parsePUTData) Timer.CallAfter(updateMuteDelay, 2) end function updateMuteDelay() fnSendGetCommand(apiAudioMute, parseAudioMuteData) end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioMuteData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioMuteData(tbl, code, data, err, headers) print(string.format("[parseAudioMuteData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioMuteData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioMuteData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.AudioMute.Boolean = false else fnHeartbeatStatus(0) Controls.AudioMute.Boolean = parseJSON(json.decode(data), "enabled") end if Controls.AudioMute.Boolean then Controls.AudioMute.Legend = "Activated" AudioMuteStateIcon = AudioMuteIcon if Status.Value == 0 then Controls.DeviceTypeColor.Color = YellowAlt else Controls.DeviceTypeColor.Color = RedAlt end else Controls.AudioMute.Legend = "Deactivated" AudioMuteStateIcon = AudioUnmuteIcon if Status.Value == 0 then Controls.DeviceTypeColor.Color = GreenAlt else Controls.DeviceTypeColor.Color = RedAlt end end local icon = { DrawChrome = false, -- Draw the button face and edges IconData = AudioMuteStateIcon, } Controls.AudioLevelMuteIcon.Legend = json.encode(icon) end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioOutputsLevelData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- toMin = -60 toMax = 20 fromMin = -18 fromMax = 0 function parseAudioOutputsLevelData(tbl, code, data, err, headers) print(string.format("[parseAudioOutputsLevelData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioOutputsLevelData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioOutputsLevelData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.OutputLevelAnalog.Value = -18 Controls.OutputLevelAnalogText.String = "-18 dB" else fnHeartbeatStatus(0) local value = parseJSON(json.decode(data), "gain") Controls.OutputLevelAnalog.Value = (value - fromMin)*(toMax - toMin)/(fromMax - fromMin) + toMin Controls.OutputLevelAnalogText.String = value .. " dB" end end ----------------------------------------------------------------------------------------------------------------- --[[ AudioCustomEQLevels ----------------------------------------------------------------------------------------------------------------- Arguments: Output : AudioCustomEQLevel.Value, AudioCustomEQLevelText.String Globals : Calls : fnSend Return : Purpose : adjust the custom profile audio channel levels Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function fnEQUCustomCommand() local body = '{"gains":[' .. tostring(math.floor(arrAudioCustomEQLevels[1])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[2])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[3])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[4])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[5])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[6])) .. "," .. tostring(math.floor(arrAudioCustomEQLevels[7])) .. "]}" fnSendPutCommand(apiAudioEqualizer, body, parsePUTData) Timer.CallAfter(updateEQDelay, 2) end function updateEQDelay() fnSendGetCommand(apiAudioEqualizer, parseAudioEqualizerData) end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioEqualizerData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioEqualizerData(tbl, code, data, err, headers) print(string.format("[parseAudioEqualizerData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioEqualizerData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioEqualizerData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) arrAudioCustomEQLevels = {0,0,0,0,0,0,0} Controls.AudioCustomEQLevel1.Value = 0 Controls.AudioCustomEQLevel2.Value = 0 Controls.AudioCustomEQLevel3.Value = 0 Controls.AudioCustomEQLevel4.Value = 0 Controls.AudioCustomEQLevel5.Value = 0 Controls.AudioCustomEQLevel6.Value = 0 Controls.AudioCustomEQLevel7.Value = 0 Controls.AudioCustomEQLevel1Text.String = "0" Controls.AudioCustomEQLevel2Text.String = "0" Controls.AudioCustomEQLevel3Text.String = "0" Controls.AudioCustomEQLevel4Text.String = "0" Controls.AudioCustomEQLevel5Text.String = "0" Controls.AudioCustomEQLevel6Text.String = "0" Controls.AudioCustomEQLevel7Text.String = "0" else fnHeartbeatStatus(0) local EQTable = parseJSON(json.decode(data), "gains") arrAudioCustomEQLevels[1] = parseJSON(EQTable,1) Controls.AudioCustomEQLevel1.Value = arrAudioCustomEQLevels[1] Controls.AudioCustomEQLevel1Text.String = arrAudioCustomEQLevels[1] arrAudioCustomEQLevels[2] = parseJSON(EQTable,2) Controls.AudioCustomEQLevel2.Value = arrAudioCustomEQLevels[2] Controls.AudioCustomEQLevel2Text.String = arrAudioCustomEQLevels[2] arrAudioCustomEQLevels[3] = parseJSON(EQTable,3) Controls.AudioCustomEQLevel3.Value = arrAudioCustomEQLevels[3] Controls.AudioCustomEQLevel3Text.String = arrAudioCustomEQLevels[3] arrAudioCustomEQLevels[4] = parseJSON(EQTable,4) Controls.AudioCustomEQLevel4.Value = arrAudioCustomEQLevels[4] Controls.AudioCustomEQLevel4Text.String = arrAudioCustomEQLevels[4] arrAudioCustomEQLevels[5] = parseJSON(EQTable,5) Controls.AudioCustomEQLevel5.Value = arrAudioCustomEQLevels[5] Controls.AudioCustomEQLevel5Text.String = arrAudioCustomEQLevels[5] arrAudioCustomEQLevels[6] = parseJSON(EQTable,6) Controls.AudioCustomEQLevel6.Value = arrAudioCustomEQLevels[6] Controls.AudioCustomEQLevel6Text.String = arrAudioCustomEQLevels[6] arrAudioCustomEQLevels[7] = parseJSON(EQTable,7) Controls.AudioCustomEQLevel7.Value = arrAudioCustomEQLevels[7] Controls.AudioCustomEQLevel7Text.String = arrAudioCustomEQLevels[7] end end --Custom Level 1 Controls.AudioCustomEQLevel1.EventHandler = function() arrAudioCustomEQLevels[1] = Controls.AudioCustomEQLevel1.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 2 Controls.AudioCustomEQLevel2.EventHandler = function() arrAudioCustomEQLevels[2] = Controls.AudioCustomEQLevel2.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 3 Controls.AudioCustomEQLevel3.EventHandler = function() arrAudioCustomEQLevels[3] = Controls.AudioCustomEQLevel3.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 4 Controls.AudioCustomEQLevel4.EventHandler = function() arrAudioCustomEQLevels[4] = Controls.AudioCustomEQLevel4.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 5 Controls.AudioCustomEQLevel5.EventHandler = function() arrAudioCustomEQLevels[5] = Controls.AudioCustomEQLevel5.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 6 Controls.AudioCustomEQLevel6.EventHandler = function() arrAudioCustomEQLevels[6] = Controls.AudioCustomEQLevel6.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --Custom Level 7 Controls.AudioCustomEQLevel7.EventHandler = function() arrAudioCustomEQLevels[7] = Controls.AudioCustomEQLevel7.Value fnEQUCustomCommand() end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioInputMicSensitivityData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioInputMicSensitivityData(tbl, code, data, err, headers) print(string.format("[parseAudioInputMicSensitivityData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioInputMicSensitivityData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioInputMicSensitivityData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.OutputLevelAnalogText.String = "" else fnHeartbeatStatus(0) Controls.SensitivityThreshold.String = parseJSON(json.decode(data), "sourceDetectionThreshold") end end ----------------------------------------------------------------------------------------------------------------- --[[ TruVoice Lift ----------------------------------------------------------------------------------------------------------------- Arguments: Output : TruVoiceLift.Boolean, TruVoiceLift.Legend Globals : Calls : fnSend Return : Purpose : Set the TruVoiceLift on or off Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- Controls.TruVoiceLift.EventHandler = function() local body if Controls.TruVoiceLift.Boolean then body = '{"voiceLiftEnabled":true}' else body = '{"voiceLiftEnabled":false}' end fnSendPutCommand(apiAudioVoiceLift, body, parsePUTData) Timer.CallAfter(updateVoiceLiftDelay, 2) end function updateVoiceLiftDelay() fnSendGetCommand(apiAudioVoiceLift, parseAudioVoiceLiftData) end ----------------------------------------------------------------------------------------------------------------- --[[ Audio ~parseAudioVoiceLiftData ----------------------------------------------------------------------------------------------------------------- Arguments: tbl, code, data, err, headers Output : Controls.DeviceFirmware.String Globals : Calls : fnHeartbeatStatus parseJSON Return : Purpose : passes data from HTTP GET request to recursive function to sort data into an array Notes : ----------------------------------------------------------------------------------------------------------------- ]]-- function parseAudioVoiceLiftData(tbl, code, data, err, headers) print(string.format("[parseAudioVoiceLiftData] Http response from '%s': Return Code=%i; Error=%s", tbl.Url, code, err or "None")) print(string.format("[parseAudioVoiceLiftData] data: %s", data)) if math.floor(code) ~= 200 then print(string.format("[parseAudioVoiceLiftData] error: " .. math.floor(code) .. " : " .. httpErrors[math.floor(code)])) Controls.TruVoiceLift.Boolean = false else fnHeartbeatStatus(0) Controls.TruVoiceLift.Boolean = parseJSON(json.decode(data), "voiceLiftEnabled") end if Controls.TruVoiceLift.Boolean then Controls.TruVoiceLift.Legend = "Activated" else Controls.TruVoiceLift.Legend = "Deactivated" end end ----------------------------------------------------------------------------------------------------------------- -- EventHandler wait for IPAddress.String to update before initializing runtime ----------------------------------------------------------------------------------------------------------------- IPAddress.EventHandler = function() print("IP Address: " .. IPAddress.String) if IPAddress.String ~= "" and Username.String ~= "" and Password.String ~= "" then Init() else ReportStatus("MISSING", "IP is missing") end end Username.EventHandler = function() print("Username: " .. Username.String) if IPAddress.String ~= "" and Username.String ~= "" and Password.String ~= "" then Init() else ReportStatus("MISSING", "Username is missing") end end Password.EventHandler = function() print("Password: " .. Password.String) if IPAddress.String ~= "" and Username.String ~= "" and Password.String ~= "" then Init() else ReportStatus("MISSING", "Password is missing") end end ----------------------------------------------------------------------------------------------------------------- -- ----------------------------------------------------------------------------------------------------------------- if IPAddress.String ~= "" and Username.String ~= "" and Password.String ~= "" then Init() else ReportStatus("MISSING", "IP, Username or Password is missing") end ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --Setup ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- Controls.CustomColor.Choices = arrColorOptions Controls.MicOnColor.Choices = arrColorOptions Controls.MicMuteColor.Choices = arrColorOptions nAudioTracking = true Controls.AudioLevelTracking.Legend = "Activated" Controls.AudioLevelTracking.Value = nAudioTracking nPositionTracking = true Controls.SourceDetectionTracking.Legend = "Activated" Controls.SourceDetectionTracking.Value = nPositionTracking ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- --end of code ----------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------- end