This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

Script integration for Acrylic Amp & Upstream audio device
#1
This script is still a work in progress, there is some unused code and optimization is certainly possible, but it already functions.

This script makes it able to control (on/off, switch source, volume) of your Acrylic Amp4 device from pushbuttons on a wall switch 
You can custom define 5 web radio stations and the text that will be displayed on the pushbutton 

Prerequisites:
  • An Acrylic Amp4/Upstream audio device connected to your lan and speakers
       
  • A zigbee, knx, enocean,... relay switch, can be a controllable AC plug
       
  • A pushbutton that can display custom text such as MDT Glasstaster (II) Smart
    Though any pushbutton will work but without station name feedback
       

The script needs 4 pushbuttons, these related group addresses have a tag attached such as 'audio_bath':
  • 1 for on/off
  • 1 for switching between sources/stations
  • 2 for up/down volume

Event script triggered by tag such as 'audio_bath'
Code:
-- https://developer.arylic.com/httpapi/#http-api ip = '192.168.1.100' -- IP Address of Acrylic Upstream AMP Device require('json') require('user.up2stream') require('socket.http') local DEBUG = false -- list of stations to choose from, limited to 5 radio stations and 2 special sources (usb and wifi) -- special care for usb and wifi naming which cannot be renamed since used in script to construct the correct http api url -- though they can be replaced by 2 extra radiostations, in the 4Stream Android app you can change source also local stations = {     {'Radio2','http://icecast.vrtcdn.be/ra2ovl-high.mp3'},   {'QMusic','https://playerservices.streamtheworld.com/api/livestream-redirect/QMUSIC.mp3'},   {'Nostalgie','http://playerservices.streamtheworld.com/api/livestream-redirect/NOSTALGIEWHATAFEELINGAAC.aac'},   {'StuBru','http://icecast.vrtcdn.be/stubru-high.mp3'},   {'ZenFM','https://23613.live.streamtheworld.com/TOPZEN.mp3'},   {'usb','3'},   {'wifi','wifi'}   } local StationSelected -- The Current selected station number, based on Table Key number local channelname -- The Channel name, the first nested table field from stations table local grp_onoff_obj = '5/0/1' -- Button on/off object for device local grp_onoff_FB_obj = '5/1/1' -- Button on/off Feedback object for device local grp_channelswitch_obj = '5/0/2' -- Button channel switching object for device local grp_channelswitch_FB_obj = '5/1/2' -- Button channel switching Feedback object for device local grp_volumeUP_obj = '5/0/4' -- Button Volume UP object for device local grp_volumeDOWN_obj = '5/0/5' -- Button Volume DOWN object for device local grp_volumeUP_FB_obj = '5/1/4' -- Button Volume UP Feedback object for device local grp_volumeDOWN_FB_obj = '5/1/5' -- Button Volume DOWN Feedback object for device local grp_switch_obj = '8/6/10' -- AC Plug Switch on/off object for device local grp_trigger_obj = event.dst -- Grp object that triggered this script, since script is triggered by TAG we need to identify the grp object local message_obj = '8/5/6' -- MDT Glass Pushbutton ASCII Message Grp Address to custom name pushbutton based on state, here used for displaying channel name / radio station local RoomChannel = 'Channel_Badk' AudioTb = storage.get('Audio_UpStream') -- Get audio table from storage (where last station is stored) if type(AudioTb) ~= 'table' or next(AudioTb) == nil then -- if no table exists   AudioTb = {} -- create an empty table   AudioTb[RoomChannel] = 1 -- set initial station to 1 end -- DEVICE ON/OFF BUTTON if grp_trigger_obj == grp_onoff_obj then -- if on/off button is pressed   if event.getvalue() then -- if group object is true / ON     if DEBUG == true then log('activate') end     grp.checkwrite(grp_switch_obj, true) -- switch AC plug to ON     grp.checkwrite(grp_onoff_FB_obj, true) -- on/off group object feedback to ON     grp.checkwrite(message_obj, '1/3') -- show waiting message above pushbutton     pingdevice(ip) -- first check and wait till device is pingable     grp.checkwrite(message_obj, '2/3')  -- see prev comment     internetup() -- second check and wait till internet is up for device     grp.checkwrite(message_obj, '3/3')  -- see prev comment     os.sleep(2) -- Optionally give the device some extra time to be ready to receive to weblink     StationSelected = AudioTb[RoomChannel] -- Load the last stored selected station from table     -- Check which station was last used, if usb or wifi use specific api url string, else use webradio url string     if stations[StationSelected][1] == 'usb' then -- if first field of nested table has 'usb' in it       station = Up2_PlayUSB..stations[StationSelected][2] -- use specific link and construct on selected file in stations list       channelname = stations[StationSelected][1] -- set channelname to 'usb' (from stations table list)     elseif stations[StationSelected][1] == 'wifi' then -- if first field of nested table has 'wifi' in it       station = setPlayerCmdSource..stations[StationSelected][2] -- use specific link and construct to play from 4Stream App or Spotify...       channelname = stations[StationSelected][1] -- set channelname to 'wifi' (from stations table list)     else -- if anything else than usb or wifi we assume its a web radio station       station = setPlayerCmdWebRadio..stations[StationSelected][2]  -- use specific link and construct to play selected radio station from stations table list       channelname = stations[StationSelected][1] -- set channelname to radio station name from stations table list     end        grp.checkwrite(message_obj, channelname) -- show selected channelname message above pushbutton     socket.http.TIMEOUT = 70     socket.http.request(station) -- send command url to device to start playing the last stored station or source   else -- if group object is false / OFF     if DEBUG == true then log('uitschakelen') end     grp.checkwrite(grp_onoff_FB_obj, false) -- set grp object device on/off feedback to false     grp.checkwrite(grp_switch_obj, false)   -- set grp object AC plug on/off to false, switching off     grp.checkwrite(message_obj, 'goodbye') -- show goodbye message above pushbutton     os.sleep(3) -- wait for 3 seconds     grp.checkwrite(message_obj, false) -- show nothing above pushbutton     grp.checkwrite(grp_channelswitch_FB_obj, 0) -- set grp object channel button switch feedback to 0 / false   end end -- CHANNEL SELECTION BUTTON if grp_trigger_obj == grp_channelswitch_obj then -- if channel switch button is pressed   grp.checkwrite(grp_channelswitch_FB_obj, 1) -- set channel switch group object feedback to 1 / on   StationSelected = AudioTb[RoomChannel] + 1 -- get value from table/storage and add 1   if StationSelected == 8 then StationSelected = 1 end -- if value is 8 reset to 1, the stations list is limited to 'only' 7 items   if stations[StationSelected][1] == 'usb' then -- see prev comment     station = Up2_PlayUSB..stations[StationSelected][2] -- see prev comment     channelname = stations[StationSelected][1] -- see prev comment   elseif stations[StationSelected][1] == 'wifi' then -- see prev comment     station = setPlayerCmdSource..stations[StationSelected][2] -- see prev comment     channelname = stations[StationSelected][1] -- see prev comment   else -- see prev comment     station = setPlayerCmdWebRadio..stations[StationSelected][2] -- see prev comment     channelname = stations[StationSelected][1] -- see prev comment   end   if DEBUG == true then log(channelname,station) end   socket.http.TIMEOUT = 70   socket.http.request(station) -- see prev comment     AudioTb[RoomChannel] = StationSelected -- update the table with the selected channel     grp.checkwrite(message_obj, channelname) -- see prev comment   os.sleep(1)   grp.checkwrite(grp_channelswitch_FB_obj, 0) -- see prev comment     storage.set('Audio_UpStream',AudioTb) -- write table to storage   end -- VOLUME UP / DOWN BUTTONS if grp_trigger_obj == grp_volumeUP_obj and grp.getvalue(grp_onoff_obj) == true then -- if UP button pressed and device is on   grp.checkwrite(grp_volumeUP_FB_obj, 1) -- set volume up switch group object feedback to 1 / on   grp_volume = tonumber(getdata('','vol')) -- get the current volume from device (function in user lib script)   if grp_volume >= 80 then -- if volume is more than 80         grp_volume = 80 -- keep volume at 80, is loud enough   else     grp_volume = grp_volume + 2 -- if not, set volume 2 notches higher     end   socket.http.TIMEOUT = 70   socket.http.request(Up2_VolSet..grp_volume) -- send command url to device to set volume higher   grp.checkwrite(grp_volumeUP_obj, 0) -- set volume up switch group object to 0 / off   grp.checkwrite(grp_volumeUP_FB_obj, 0) -- set volume up switch group object feedback to 0 / off elseif grp_trigger_obj == grp_volumeDOWN_obj and grp.getvalue(grp_onoff_obj) == true then -- if DOWN button pressed and device is on   grp.checkwrite(grp_volumeDOWN_FB_obj, 1) -- set volume down switch group object feedback to 1 / on   grp_volume = tonumber(getdata('','vol')) -- see prev comment   if grp_volume <= 5 then -- if volume is less than 5     grp_volume = 5 -- keep volume at 5, is quiet enough   else     grp_volume = grp_volume - 2 -- if not, set volume 2 notches lower   end   socket.http.TIMEOUT = 70     socket.http.request(Up2_VolSet..grp_volume) -- send command url to device to set volume lower   grp.checkwrite(grp_volumeDOWN_obj, 0) -- set volume down switch group object to 0 / off   grp.checkwrite(grp_volumeDOWN_FB_obj, 0) -- set volume down switch group object feedback to 0 / off end

User library script named user.up2stream
Code:
local Path = 'http://'..ip..'/httpapi.asp?command=' -- Link base path -- in use local getPlayerStatus = Path..'getPlayerStatus' local getStatusEx = Path..'getStatusEx' local setPlayerCmdSource = Path..'setPlayerCmd:switchmode:' -- add wifi, line-in, bleutooth, optical, pcusb, udisk, line-in2l local setPlayerCmd = Path..'setPlayerCmd:' local setPlayerCmdWebRadio = Path..'setPlayerCmd:play:' local Up2_VolSet = Path..'setPlayerCmd:vol:' local Up2_ShowVol = Path..'setPlayerCmd:Vol--n' local Up2_PlayUSB = Path..'setPlayerCmd:playLocalList:' -- Add INDEX number (song number) to end local Up2_SwitchPBSource = Path..'setPlayerCmd:switchmode:' --Add bluetooth, line-in, optical, udisk, wifi -- Function to ping device with timeout (to see if device is already online after power-up) function socketping(ip, port, timeout)   port = port or 80   local sock = require('socket').tcp()   sock:settimeout(timeout or 20)   local res, err = sock:connect(ip, port)   --log(res)   --log(err)   sock:close()   --status = err   --return res, err   if (res) then return true end   return false end -- Function to replace a character in a string -- Here used to get the group feedback address from the event group address that triggered this event -- Only works when group address and group address feedback have the same first and last number such as 5/0/1 and 5/1/1 function replace_char(pos, str, r)     return str:sub(1, pos-1) .. r .. str:sub(pos+1) end -- function to convert hex to character (for Acrylic http api) function hextochar(str)   local hex_to_char = {}   for idx = 0, 255 do     hex_to_char[("%02X"):format(idx)] = string.char(idx)     hex_to_char[("%02x"):format(idx)] = string.char(idx)   end     str = str:gsub("(..)", hex_to_char)   str = string.gsub( str, '&lt;', '<' )   str = string.gsub( str, '&gt;', '>' )   str = string.gsub( str, '&quot;', '"' )   str = string.gsub( str, '&apos;', "'" )   str = string.gsub( str, '&#(%d+);', function(n) return string.char(n) end )   str = string.gsub( str, '&#x(%d+);', function(n) return string.char(tonumber(n,16)) end )   str = string.gsub( str, '&amp;', '&' ) -- Be sure to do this after all others   return str end function pingdevice(ip, timeout)   local startTime = os.time()   local online = false   local i = 1   if timeout == nil then timeout = 50 end   while online == false and (os.time() - startTime < timeout) do     local pingOutput = os.execute("ping -c 1 -W 1 " .. ip)     -- Check ping successful by exit code (0 is success, anything else is failure)     if pingOutput == 0 then         online = true        -- log("Audio Device is UP")     else         --log('countdown retry:'..(timeout-i))         i = i + 1     end   end   if online == false then   --log("Audio Device is DOWN or timeout reached.")   end end function internetup(timeout)   --log('please wait')   local startTime = os.time()   local online = false   local i = 1   if timeout == nil then timeout = 60 end   socket.http.TIMEOUT = 70   while online == false and (os.time() - startTime < timeout) do     data, status, err = socket.http.request(getStatusEx)    -- log(status)     if status == 200 and data ~= 'unknown command' then       data = json.decode(data)       local internet = tonumber(data.internet)       if internet == 1 then         online = true         status = 'online'         --log('device is online and has internet')               end     else       --log('countdown: '..(timeout - i))       os.sleep(1)         i = i + 1           end   end -- log(status) end function getdata(command, key)   if command == nil then command = 'getPlayerStatus' end   if key == nil then key = 'mode' end     data, status, err = socket.http.request(getPlayerStatus)     --log(status)       data = json.decode(data)       return data[key] end
Reply


Forum Jump: