ILoveC4 Posted June 2, 2013 Share Posted June 2, 2013 I want to modify this driver to add some new commands. It isn't immediately obvious to me where the commands go...anyone have any insight? I can see how to add the command, but I can't see how to enter the code that is sent to the TV when the command is entered. does that make sense?Driver attached. Nevermind...I can't attach the driver for some reason. Here is all the code from the driver.<devicedata> <certified level="1" date="5/25/2011">Certified</certified> <c4id>7198</c4id> <manufacturer>Sharp</manufacturer> <model>LC-60LE835 [Network][DriverWorks]</model> <search_type>c4:av_gen</search_type> <creator>Control4</creator> <name>Sharp LC-60LE835</name> <small>devices_sm\tv.gif</small> <large>devices_lg\tv.gif</large> <top> </top> <bottom> </bottom> <front> </front> <back> </back> <left> </left> <right> </right> <control>lua_gen</control> <driver>DriverWorks</driver> <copyright>Copyright 2004-2007 Control4 Corporation. All rights reserved.</copyright> <created>4/21/2011 9:01:50 PM</created> <modified>10/6/2011 5:00:00 PM</modified> <OnlineCategory>tv</OnlineCategory> <proxies qty="1"> <proxy proxybindingid="5001" name="TV">tv</proxy> </proxies> <capabilities> <surround_modes type="xml"> </surround_modes> <has_discrete_volume_control>True</has_discrete_volume_control> <has_up_down_volume_control>True</has_up_down_volume_control> <has_discrete_input_select>True</has_discrete_input_select> <has_toad_input_select>True</has_toad_input_select> <has_audio>True</has_audio> <has_discrete_channel_select>True</has_discrete_channel_select> <has_toggle_mute_control>True</has_toggle_mute_control> <has_channel_up_down>True</has_channel_up_down> <video_provider_count>0</video_provider_count> <video_consumer_count>9</video_consumer_count> <audio_provider_count>1</audio_provider_count> <audio_consumer_count>5</audio_consumer_count> <has_discrete_mute_control>True</has_discrete_mute_control> <has_feedback>True</has_feedback> </capabilities> <events> </events> <connections> <connection> <id>5001</id> <facing>6</facing> <connectionname>TV</connectionname> <type>2</type> <consumer>False</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>False</linelevel> <classes> <class> <classname>TV</classname> </class> </classes> </connection> <connection> <id>6001</id> <facing>6</facing> <connectionname>Ethernet</connectionname> <type>4</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>TCP</classname> <ports> <port> <number>10002</number> <auto_connect>True</auto_connect> <monitor_connection>True</monitor_connection> <keep_connection>True</keep_connection> </port> </ports> </class> </classes> </connection> <connection proxybindingid="5001"> <id>4000</id> <facing>6</facing> <connectionname>Output</connectionname> <type>6</type> <consumer>False</consumer> <audiosource>True</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>DIGITAL_OPTICAL</classname> </class> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>7000</id> <facing>6</facing> <connectionname>Room Selection - Output</connectionname> <type>7</type> <consumer>False</consumer> <audiosource>True</audiosource> <videosource>True</videosource> <linelevel>True</linelevel> <classes> <class> <classname>AUDIO_SELECTION</classname> </class> <class> <classname>AUDIO_VOLUME</classname> </class> <class> <classname>VIDEO_SELECTION</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1001</id> <facing>6</facing> <connectionname>CABLE/TV</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>RF_CABLE</classname> </class> <class> <classname>RF_UHF_VHF</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>3002</id> <facing>6</facing> <connectionname>COMPONENT</connectionname> <type>6</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1002</id> <facing>6</facing> <connectionname>COMPONENT</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>COMPONENT</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>3003</id> <facing>6</facing> <connectionname>HDMI 1</connectionname> <type>6</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1003</id> <facing>6</facing> <connectionname>HDMI 1</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>HDMI</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1004</id> <facing>6</facing> <connectionname>HDMI 2</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>HDMI</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1005</id> <facing>6</facing> <connectionname>HDMI 3</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>HDMI</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1006</id> <facing>6</facing> <connectionname>HDMI 4</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>HDMI</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>3007</id> <facing>6</facing> <connectionname>PC IN</connectionname> <type>6</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1007</id> <facing>6</facing> <connectionname>PC IN</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>VGA</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>3008</id> <facing>6</facing> <connectionname>VIDEO 1</connectionname> <type>6</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1008</id> <facing>6</facing> <connectionname>VIDEO 1</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>COMPOSITE</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>3009</id> <facing>6</facing> <connectionname>VIDEO 2</connectionname> <type>6</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>STEREO</classname> </class> </classes> </connection> <connection proxybindingid="5001"> <id>1009</id> <facing>6</facing> <connectionname>VIDEO 2</connectionname> <type>5</type> <consumer>True</consumer> <audiosource>False</audiosource> <videosource>False</videosource> <linelevel>True</linelevel> <classes> <class> <classname>COMPOSITE</classname> </class> </classes> </connection> </connections> <config> <documentation>Control4 certified on 5/25/2011 for software released versions: 1.8.2, 2.1.0.TV CONFIGURATION:Setup:Set TV to static IP. 1. Using the remote, select the "TV" input.2. Use the menu to navigate to Initial Setup>Internet Setup>Network Setup>IP Setup.3. Set a Static IP according to your network parameters, see User Manual for details.4. Navigate to Initial Setup>Internet Setup>Network Setup>IP Control Setup.5. Set IP Control Status to "Enable".6. Add IP to driver in Composer>Connections>Network.7. If IP Port number is changed from the default of 10002 in the TV configuration, then the new Port Number must be entered in the IP Port field in the Properties field in Composer.POWER ON COMMAND SETTING:IMPORTANT NOTE - By default the TV will reject the Power On command. During installation, the TV must be turned on manually and then, using the Actions Tab, sent the appropriate ENABLE POWER_ON command.Via the Actions Tab, the TV can be configured to Accept or Reject the Power On Command. -ENABLE POWER_ON_RS232 will configure the TV to Accept the Power On Command when controlling via RS-232.-ENABLE POWER_ON_IP will configure the TV to Accept the Power On Command when controlling via IP.-DISABLE POWER_ON will configure the TV to Reject the Power On Command.PROPERTIES:-Command Delay-Milliseconds. Typically this is the amountof time that the driver will wait to send a Command after a previous Command has been sent. This is Property is not used in this driver since a Command will not be send after a previous Command until a Response is received from te TV.-Response Wait Timer Delay-Seconds. In the event that no Response is received from the TV after a Command is sent, the driver will process subsequent Commands after the amount of time specified by this Property.-Volume Ramp Delay-Milliseconds. The amount of time between Volume Up or Volume Down Commands.-Channel Buffer Timer Value. When entering Digits from the Keypad for Channel Tuning, this is the amount of time after the first Digit is entered that it will take for the SET_CHANNEL command to be sent.-Power On Delay-Seconds. This is the Delay after a Power On Command is sent before a susequnet Command will be sent. -Polling Timer Delay - Seconds. A Polling Timer is implemented to periodically poll the TV for current status of power state, currently selected input, current volume and mute state.DEVICE SPECIFIC COMMANDS:The following commands are included in this driver for use by models that support these capabilities. These commands can be accessed via Programming or Custom Buttons:SLEEPCCAV_MODEVIEW_MODEAQUOSNetC_3DOFFC_2DTO3DC_SBSC_TABC_3DTO2D_SBSC_3DTO2D_TABC_3DAUTOC_2DAUTOAPP1APP2APP3POLLING TIMER:A Polling Timer is implemented to periodically poll the TV for current status of power state, currently selected input, currently selected channel, current volume and mute state. The polling interval is dictated by the "Polling Timer Delay" which can be set via the driver's "Properties" tab.TIP: If the Polling Timer is not running when the TV is On, then the Power Delay may need to be increased.COMMAND QUEUE:All commands are stacked in order in the command queue. Once a command is sent to the TV, the next command in the queue will not be sent until the first of either of the following occurs1) and acknolwledgement is received from the TV2) the amount of time delcared in the "Response Timeout" elapsesThe "Command Delay" and "Volume Ramp Delay" dictate how often the command queue is checked. When checked, the next commandin the queue will be sent to the TV unless it is waiting for a response from a command sent previously.The "Power On Delay" dictates how long the driver will wait before sending the next command in the queue after the "ON" command is sent.The "Response Timeout", "Command Delay", "Volume Ramp Delay" and "Power On Delay" may be set via the driver's "Properties" tab.</documentation> <commands> <command> <name>SLEEP</name> <description>SLEEP</description> </command> <command> <name>CC</name> <description>CC</description> </command> <command> <name>AV_MODE</name> <description>AV MODE TOGGLE</description> </command> <command> <name>VIEW_MODE</name> <description>VIEW MODE TOGGLE</description> </command> <command> <name>AQUOSNet</name> <description>AQUOSNet</description> </command> <command> <name>C_3DOFF</name> <description>3D OFF</description> </command> <command> <name>C_2DTO3D</name> <description>2D TO 3D</description> </command> <command> <name>C_SBS</name> <description>SBS</description> </command> <command> <name>C_TAB</name> <description>TAB</description> </command> <command> <name>C_3DTO2D_SBS</name> <description>3D TO 2D (SBS)</description> </command> <command> <name>C_3DTO2D_TAB</name> <description>3D TO 2D (TAB)</description> </command> <command> <name>C_3DAUTO</name> <description>3D AUTO</description> </command> <command> <name>C_2DAUTO</name> <description>2D AUTO</description> </command> <command> <name>APP1</name> <description>APP1</description> </command> <command> <name>APP2</name> <description>APP2</description> </command> <command> <name>APP3</name> <description>APP3</description> </command> </commands> <properties> <property> <name>IP Port</name> <type>RANGED_INTEGER</type> <minimum>80</minimum> <maximum>99999</maximum> <default>10002</default> <readonly>false</readonly> </property> <property> <name>Connected To Network</name> <type>STRING</type> <default>false</default> <readonly>true</readonly> </property> <property> <name>Debug Mode</name> <type>LIST</type> <items> <item>Off</item> <item>Print</item> <item>Log</item> <item>Print and Log</item> </items> <default>Off</default> <readonly>false</readonly> </property> <property> <name>Command Delay-Milliseconds</name> <type>RANGED_INTEGER</type> <minimum>50</minimum> <maximum>2500</maximum> <default>250</default> <readonly>false</readonly> </property> <property> <name>Volume Ramp Delay-Milliseconds</name> <type>RANGED_INTEGER</type> <minimum>50</minimum> <maximum>500</maximum> <default>250</default> <readonly>false</readonly> </property> <property> <name>Direct Channel Tuning</name> <type>LIST</type> <items> <item>Analog</item> <item>Digital Air</item> <item>Digital Cable - Two Part</item> <item>Digital Cable - One Part</item> </items> <minimum>0</minimum> <maximum>0</maximum> <default>Digital Air</default> <readonly>false</readonly> </property> <property> <name>Channel Buffer Timer Value</name> <type>RANGED_INTEGER</type> <minimum>1</minimum> <maximum>5</maximum> <default>3</default> <readonly>false</readonly> </property> <property> <name>Response Wait Timer Delay-Seconds</name> <type>RANGED_INTEGER</type> <minimum>0</minimum> <maximum>25</maximum> <default>10</default> <readonly>false</readonly> </property> <property> <name>Power On Delay-Seconds</name> <type>RANGED_INTEGER</type> <minimum>0</minimum> <maximum>25</maximum> <default>15</default> <readonly>false</readonly> </property> <property> <name>Polling Timer Delay-Seconds</name> <type>RANGED_INTEGER</type> <minimum>1</minimum> <maximum>60</maximum> <default>5</default> <readonly>false</readonly> </property> </properties> <actions> <action> <name>ENABLE POWER_ON_RS232</name> <command>ENABLE POWER_ON_RS232</command> </action> <action> <name>ENABLE POWER_ON_IP</name> <command>ENABLE POWER_ON_IP</command> </action> <action> <name>DISABLE POWER_ON</name> <command>DISABLE POWER_ON</command> </action> <action> <name>Destroy All Timers</name> <command>Destroy Timers</command> </action> </actions> <power_management_method>DiscreteCodes</power_management_method> <irsettings> </irsettings> <power_command_delay>0</power_command_delay> <power_delay>12</power_delay> <power_command_needed>True</power_command_needed> <rfs> <rf>rf_cable</rf> <rf>rf_uhf_vhf</rf> </rfs> <serialsection> <serialcodes /> </serialsection> <script><![CDATA[tSurroundCommands = {}tOutputConnMap = {[0] = 'Output',}tInputConnMapByID = {[1] = {Name = 'CABLE/TV',BindingID = 5001,},[2] = {Name = 'COMPONENT',BindingID = 5001,},[3] = {Name = 'HDMI 1',BindingID = 5001,},[4] = {Name = 'HDMI 2',BindingID = 5001,},[5] = {Name = 'HDMI 3',BindingID = 5001,},[6] = {Name = 'HDMI 4',BindingID = 5001,},[7] = {Name = 'PC IN',BindingID = 5001,},[8] = {Name = 'VIDEO 1',BindingID = 5001,},[9] = {Name = 'VIDEO 2',BindingID = 5001,},}tInputConnMapByName = {['CABLE/TV'] = {ID = 1,BindingID = 5001,},['COMPONENT'] = {ID = 2,BindingID = 5001,},['HDMI 1'] = {ID = 3,BindingID = 5001,},['HDMI 2'] = {ID = 4,BindingID = 5001,},['HDMI 3'] = {ID = 5,BindingID = 5001,},['HDMI 4'] = {ID = 6,BindingID = 5001,},['PC IN'] = {ID = 7,BindingID = 5001,},['VIDEO 1'] = {ID = 8,BindingID = 5001,},['VIDEO 2'] = {ID = 9,BindingID = 5001,},}g_PowerState = nilidConnectToNetworkTimer = 0tPendingCommands = {}tEmitCommands = {}idBusyTimer = 0g_debugprint = falseg_debuglog = falsehexmap = { ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15,}ChannelCommands = ''ChannelRampTimerID = 0tVolRampTimerID = {}tVolumeCommands = {}tVolumeCommandNames = {}tCurrentVolume = {}tMaxVolume = {}CMDS = {['DISABLE POWER_ON'] = 'RSPW0 ',['ENABLE POWER_ON_RS232'] = 'RSPW1 ',['ENABLE POWER_ON_IP'] = 'RSPW2 ',['ON'] = 'POWR1 ',['OFF'] = 'POWR0 ',['MUTE_ON'] = 'MUTE1 ',['MUTE_OFF'] = 'MUTE2 ',['MUTE_TOGGLE'] = 'MUTE0 ',['TV_VIDEO'] = 'ITVD0 ',['INPUT_TOGGLE'] = 'ITGDx ', ['PULSE_CH_UP'] = 'CHUP1 ',['PULSE_CH_DOWN'] = 'CHDW1 ',['START_CH_UP'] = 'CHUP1 ',['START_CH_DOWN'] = 'CHDW1 ',['PULSE_ASPECT_RATIO'] = 'WIDE0 ',['QUERY_POWER_STATE'] = 'POWR? ',['QUERY_MUTE_STATE'] = 'MUTE? ',['GET_IS_MUTED'] = 'MUTE? ',['QUERY_VOLUME_STATE'] = 'VOLM0? ',['QUERY_INPUT_STATE'] = 'IAVD? ',['NUMBER_0']='RCKY00 ', ['NUMBER_1']='RCKY01 ', ['NUMBER_2']='RCKY02 ', ['NUMBER_3']='RCKY03 ', ['NUMBER_4']='RCKY04 ', ['NUMBER_5']='RCKY05 ', ['NUMBER_6']='RCKY06 ', ['NUMBER_7']='RCKY07 ', ['NUMBER_8']='RCKY08 ', ['NUMBER_9']='RCKY09 ',['STAR']='RCKY10 ',['INFO']='RCKY13 ', --Display['RECALL']='RCKY30 ',['MUTE_TOGGLE']='RCKY31 ',['PULSE_VOL_DOWN']='RCKY32 ',['PULSE_VOL_UP']='RCKY33 ',['MENU']='RCKY38 ',--['ENTER']='RCKY40 ',['UP']='RCKY41 ',['DOWN']='RCKY42 ',['LEFT']='RCKY43 ',['RIGHT']='RCKY44 ',['PREV']='RCKY45 ',--['CANCEL']='RCKY46 ',['PROGRAM_A']='RCKY50 ',['PROGRAM_B']='RCKY51 ',['PROGRAM_C']='RCKY52 ',['PROGRAM_D']='RCKY53 ',['APP1']='RCKY55 ',['APP2']='RCKY56 ',['APP3']='RCKY57 ',['SLEEP']='RCKY24 ',['CC']='RCKY27 ',['CLOSED_CAPTIONED']='RCKY27 ',['AV_MODE']='RCKY28 ',['VIEW_MODE']='RCKY29 ',['PULSE_ASPECT_RATIO']='RCKY29 ',['AQUOSNet']='RCKY37 ',['C_3DOFF']='TDCH0 ',['C_2DTO3D']='TDCH1 ',['C_SBS']='TDCH2 ',['C_TAB']='TDCH3 ',['C_3DTO2D_SBS']='TDCH4 ',['C_3DTO2D_TAB']='TDCH5 ',['C_3D_AUTO']='TDCH6 ',['C_2D_AUTO']='TDCH7 ',}QUERY = {['ON']='POWR? ',['OFF']='POWR? ',['MUTE_ON']='MUTE? ',['MUTE_OFF']='MUTE? ',['PULSE_VOL_UP']='VOLM0? ',['PULSE_VOL_DOWN']='VOLM0? ',['SET_VOLUME_LEVEL']='VOLM0? ',['SET_INPUT']='IAVD? ',}tInputCommandMap = {['CABLE/TV'] = 'ITVD0 ',['HDMI 1'] = 'IAVD1 ',['HDMI 2'] = 'IAVD2 ',['HDMI 3'] = 'IAVD3 ',['HDMI 4'] = 'IAVD4 ',['COMPONENT'] = 'IAVD5 ',['VIDEO 1'] = 'IAVD6 ',['VIDEO 2'] = 'IAVD7 ',['PC IN'] = 'IAVD8 ',}tInputResponseMap = {[0]='CABLE/TV',[1]='HDMI 1',[2]='HDMI 2',[3]='HDMI 3',[4]='HDMI 4',[5]='COMPONENT',[6]='VIDEO',[7]='VIDEO 2',[8]='PC IN',}mPort = tonumber(Properties['IP Port'])mNetConnected = tostring(Properties['Connected To Network'])intraCommandDelayValue = tonumber(Properties['Command Delay-Milliseconds'])intraVolRampDelayValue = tonumber(Properties['Volume Ramp Delay-Milliseconds'])g_DirectChannelTuning = tostring(Properties['Direct Channel Tuning'])g_ChannelBufferTimerValue = tonumber(Properties['Channel Buffer Timer Value'])ResponseWaitTimerDelayValue = tonumber(Properties['Response Wait Timer Delay-Seconds'])powerOnDelayValue = tonumber(Properties['Power On Delay-Seconds'])PollingTimerValue = tonumber(Properties['Polling Timer Delay-Seconds'])function OnPropertyChanged(strProperty) if (strProperty == 'Debug Mode') then if (Properties[strProperty] == 'Off') then g_debugprint = false g_debuglog = false g_DebugTimer = C4:KillTimer(g_DebugTimer) g_DebugTimer = 0 end if (Properties[strProperty] == 'Print') then g_debugprint = true g_debuglog = false startDebugTimer() end if (Properties[strProperty] == 'Log') then g_debugprint = false g_debuglog = true startDebugTimer() end if (Properties[strProperty] == 'Print and Log') then g_debugprint = true g_debuglog = true startDebugTimer() end elseif (strProperty == 'Response Wait Timer Delay-Seconds') then ResponseWaitTimerDelayValue = tonumber(Properties['Response Wait Timer Delay-Seconds']) PersistData['Response Wait Timer Delay-Seconds']=Properties['Response Wait Timer Delay-Seconds'] elseif (strProperty == 'Power On Delay-Seconds') then powerOnDelayValue = tonumber(Properties['Power On Delay-Seconds']) PersistData['Power On Delay-Seconds']=Properties['Power On Delay-Seconds'] elseif (strProperty == 'Channel Buffer Timer Value') then g_ChannelBufferTimerValue = tonumber(Properties['Channel Buffer Timer Value']) PersistData['Channel Buffer Timer Value']=Properties['Channel Buffer Timer Value'] elseif (strProperty == 'Direct Channel Tuning') then g_DirectChannelTuning = tostring(Properties['Direct Channel Tuning']) PersistData['Direct Channel Tuning']=Properties['Direct Channel Tuning'] elseif (strProperty == 'Polling Timer Delay-Seconds') then PollingTimerValue = tonumber(Properties['Polling Timer Delay-Seconds']) PersistData['Polling Timer Delay-Seconds']=Properties['Polling Timer Delay-Seconds'] elseif (strProperty == 'IP Port') then mPort = tonumber(Properties['IP Port']) PersistData['IP Port']=Properties['IP Port'] endendfunction OnTimerExpired(idTimer) if (idTimer == idEmitCommandsTimer) then if tEmitCommands[1] ~= nil then if (bOKtoEmit == true) or (bOKtoEmit == nil) then dbg('SendToNetwork:' .. tEmitCommands[1][1]) C4:SendToNetwork(6001, tonumber(mPort), tEmitCommands[1][1]) if (tEmitCommands[1][2] == true) then idResponseWaitTimer = C4:AddTimer(powerOnDelayValue, 'SECONDS', false) bPowerOnSequence=true else idResponseWaitTimer = C4:AddTimer(ResponseWaitTimerDelayValue, 'SECONDS', false) bPowerOnSequence=false end g_CurrentCommand=tEmitCommands[1][3] table.remove(tEmitCommands, 1) bOKtoEmit = false if (tEmitCommands[1] == nil) then C4:KillTimer(idEmitCommandsTimer) idEmitCommandsTimer = nil end end end elseif (idTimer == idResponseWaitTimer) then idResponseWaitTimer = C4:KillTimer(idResponseWaitTimer) if (bPowerOnSequence==true) then bPowerOnSequence=false send_polling() end bOKtoEmit = true dbg('OnTimerExpired: ResponseWaitTimer - OK to Emit set to True') elseif (idTimer == idPollingTimer) then -- Send a status query on the main port... -- If we haven't gotten a response, increment the 'not checked in'... if it hits 3, disconnect all ports... gLastCheckin = gLastCheckin or 0 gLastCheckin = gLastCheckin + 1 if (gLastCheckin > 2) then if (mNetConnected == true) then C4:NetDisconnect(6001, mPort) dbg("Failed to receive poll responses... Disconnecting...") C4:ErrorLog("Sharp TV device is not responding... Disconnecting...") end end -- Send Poll Packet if we're ONLINE... if (mNetConnected == true) then send_polling() end elseif (idTimer == gReconnectTimer) then dbg("Attempting to reconnect to Sharp TV...") C4:ErrorLog("Attempting to reconnect to Sharp TV...") local bTrying = false gReconnectTimer = C4:KillTimer(gReconnectTimer) if (gNetworkStatus == "OFFLINE") then -- Try to reconnect to the Sharp Control port... C4:NetDisconnect(6001, mPort) C4:NetConnect(6001, mPort) bTrying = true end if (bTrying) then gReconnectTimer = C4:AddTimer(5, "SECONDS") end elseif (idTimer == g_ChannelBufferTimer) then CMDS.SET_CHANNEL({CHANNEL=g_ChannelBuffer,},'SET_CHANNEL') g_ChannelBufferTimer = C4:KillTimer(g_ChannelBufferTimer) g_ChannelBufferTimer=nil g_ChannelBuffer=nil elseif (idTimer==g_VolRampTimerID) then local cmd if (g_VolumeRamp == 'UP') then cmd=CMDS.PULSE_VOL_UP .. '\r' g_CurrentCommand='PULSE_VOL_UP' else cmd=CMDS.PULSE_VOL_DOWN .. '\r' g_CurrentCommand='PULSE_VOL_DOWN' end --if (bOKtoEmit == true) or (bOKtoEmit == nil) then C4:SendToSerial(1, cmd) dbg('C4:SendToSerial: ' .. cmd) --idResponseWaitTimer = C4:AddTimer(ResponseWaitTimerDelayValue, 'SECONDS', false) bPowerOnSequence=false --bOKtoEmit = false --end elseif (idTimer==ChannelRampTimerID) then emit(ChannelCommands) elseif (idTimer == g_DebugTimer) then dbg('Turning Debug Mode back to Off [default] (timer expired)') C4:UpdateProperty('Debug Mode', 'Off') g_debugprint = false g_debuglog = false g_DebugTimer = C4:KillTimer(g_DebugTimer) else dbg('DESTROYING STRAY TIMER: ' .. idTimer) C4:KillTimer(idTimer) endendfunction ReceivedFromNetwork(idBinding, nPort, strData) dbg('Received something from network on binding ' .. idBinding) if (g_debugprint) then hexdump(strData) end processResponse(strData)endfunction OnConnectionStatusChanged(idBinding, nPort, strStatus) dbg("OnConnectionStatusChanged[" .. idBinding .. " (" .. nPort .. ")]: " .. strStatus) if (idBinding == 6001) then gNetworkStatus=strStatus if (strStatus == "ONLINE") then mNetConnected = true gLastCheckin=0 C4:UpdateProperty('Connected To Network','true') C4:ErrorLog("Connected to Sharp TV...") if (idPollingTimer) then C4:KillTimer(idPollingTimer) end idPollingTimer = C4:AddTimer(PollingTimerValue, "SECONDS", true) -- 5 second repeating timer... else mNetConnected = false C4:UpdateProperty('Connected To Network','false') -- Try a re-connect of the device ... if (gReconnectTimer == nil) or (gReconnectTimer == 0) then gReconnectTimer = C4:AddTimer(5, "SECONDS") C4:NetDisconnect(6001, mPort) C4:NetConnect(6001, mPort) end end endendfunction ReceivedFromProxy(idBinding, strCommand, tParams) dbg('ReceivedFromProxy: ' .. strCommand) if tParams==nil then tParams={} end tParams['BindingID'] = idBinding if (CMDS[strCommand] ~= nil) and (type(CMDS[strCommand])=='function') then CMDS[strCommand] (tParams, strCommand) elseif (CMDS[strCommand] ~= nil) then emit(CMDS[strCommand], strCommand, tParams.OUTPUT) else dbg('ReceivedFromProxy - Command not defined: '.. strCommand) endendfunction ExecuteCommand(Command, Parameters) dbg('ExecuteCommand: ' .. Command) if (CMDS[Command] ~= nil) and (type(CMDS[Command])=='function') then CMDS[Command] (Parameters, Command) elseif (CMDS[Command] ~= nil) then emit(CMDS[Command], Command) else dbg('ExecuteCommand - Command not defined: '.. Command) endendfunction emit(strCommand, strCommandName, lngOutputID) local bUsePowerOnDelay = false if (strCommandName=='ON') then if (g_PowerState == nil) or (g_PowerState == 'OFF') then bUsePowerOnDelay = true dbg('Emit: Using Power Delay for ON Command') if ((idPollingTimer==nil) or (idPollingTimer==0)) then dbg('Set Polling Timer') idPollingTimer = C4:AddTimer(PollingTimerValue, 'SECONDS', true) end else dbg('Skipping ON command, unit is already ON') return end elseif (strCommandName=='OFF') then tSetInputTrack=nil gSerialBuf = '' if (idPollingTimer) then dbg('Kill Polling Timer') idPollingTimer = C4:KillTimer(idPollingTimer) end else if ((idPollingTimer==nil) or (idPollingTimer==0)) then dbg('Set Polling Timer') idPollingTimer = C4:AddTimer(PollingTimerValue, 'SECONDS', true) end end strCommand = strCommand .. '\r' dbg('Emit: ' .. strCommand) table.insert(tEmitCommands, {strCommand, bUsePowerOnDelay,strCommandName}) if idEmitCommandsTimer == nil then idEmitCommandsTimer = C4:AddTimer(intraCommandDelayValue, 'MILLISECONDS', true) endendfunction processResponse(msg) gLastCheckin = 0 local NormalResponse='OK\r' local ProblemResponse='ERR\r' if (bPowerOnSequence==true) then dbg('AckInterpreter: bPowerOnSequence - Ignore Response, Power On Delay in Effect') return else bOKtoEmit = true idResponseWaitTimer = C4:KillTimer(idResponseWaitTimer) end if (msg==NormalResponse) then dbg('processResponse for ' .. g_CurrentCommand .. ', NormalResponse - OKtoEmit set to True') if (g_VolumeRamp=='UP') or (g_VolumeRamp=='DOWN') then --skip query during volume ramping else if (QUERY[g_CurrentCommand]~=nil) then emit(QUERY[g_CurrentCommand], 'QUERY ' .. g_CurrentCommand) end end return elseif (msg==ProblemResponse) then if (g_CurrentCommand=='QUERY SET_INPUT') or (g_CurrentCommand=='QUERY INPUT') then --CABLE/TV input returns ERR when queried with 'IAVD' syntax msg=0 else dbg('processResponse for ' .. g_CurrentCommand .. ', ProblemResponse - OKtoEmit set to True') return end end local response = g_CurrentCommand if (response=='QUERY ON') or (response=='QUERY OFF') or (response=='QUERY POWER') then local power local val = string.sub(msg,1,1) if val == '1' then power='ON' elseif val == '0' then power='OFF' end if (power==nil) then dbg('Unhandled Power Query Response, ' .. msg) return end dbg('processResponse for ' .. g_CurrentCommand .. ', Status: ' .. power) if (g_PowerState~=power) then g_PowerState = power C4:SendToProxy(5001, power, {}) dbg('Sent powerState to proxy: ' .. power) end elseif (string.find(response,'INPUT')~=nil) then -- bVideoOnly is workaround for TV proxy bug that affects Current Input in Composer Programming -- if connection has audio then it is considered audio, if not then it is considered video local bVideoOnly=false local id = tonumber(string.sub(msg,1,1)) local name=tInputResponseMap[id] local input=tInputConnMapByName[name].ID if (name=='HDMI 2') or (name=='HDMI 3') or (name=='HDMI 4') then bVideoOnly=true end dbg('processResponse for ' .. g_CurrentCommand .. ', Status: ' .. name) --3000 Audio, 1000 Video if (input~=nil) then if (g_CurrentInput~=input) then g_CurrentInput=input if (bVideoOnly==true) then C4:SendToProxy(5001,'INPUT_CHANGED', {INPUT=input + 1000}) else C4:SendToProxy(5001,'INPUT_CHANGED', {INPUT=input + 3000}) end g_CurrentInputID=input + 3000 dbg('Sent INPUT_CHANGED to: ' .. name) end end elseif (string.find(response,'MUTE')~=nil) then local mute local val = string.sub(msg,1,1) if (val == '2') then mute='False' elseif (val == '1') then mute='True' end if (mute==nil) then dbg('Unhandled Mute Query Response, ' .. msg) return end dbg('processResponse for ' .. g_CurrentCommand .. ', Status: ' .. mute) --Mute notification only supported by TV proxy in 2.0 and forward if (g_Mute~=mute) then g_Mute=mute C4:SendToProxy(5001,'MUTE_CHANGED', {MUTE = g_Mute, OUTPUT = 4000}) dbg('Sent muteState to proxy: ' .. g_Mute) end elseif (string.find(response,'VOL')~=nil) then --Volume notification only supported by TV proxy in 2.0 and forward local volume=tonumber(string.sub(msg,1,2)) volume=processVolumeLevel(volume, 0, 60, 0, 100) dbg('processResponse for ' .. g_CurrentCommand .. ', Status: ' .. volume) if (CurrentVolume~=volume) then CurrentVolume=volume C4:SendToProxy(5001,'VOLUME_LEVEL_CHANGED', {LEVEL = volume, OUTPUT = 4000}) dbg('Sent VOLUME_LEVEL_CHANGED to proxy: ' .. volume ..'%') end endendfunction OnDriverDestroyed() if (g_DebugTimer) then g_DebugTimer = C4:KillTimer(g_DebugTimer) end for lngOutputID,VolRampTimerID in pairs(tVolRampTimerID) do if (VolRampTimerID) then VolRampTimerID = C4:KillTimer(VolRampTimerID) end end if (idEmitCommandsTimer) then idEmitCommandsTimer = C4:KillTimer(idEmitCommandsTimer) idEmitCommandsTimer = nil end if (ChannelRampTimerID) then ChannelRampTimerID = C4:KillTimer(ChannelRampTimerID) end if (idConnectToNetworkTimer) then idConnectToNetworkTimer = C4:KillTimer(idConnectToNetworkTimer) end if (idBusyTimer) then idBusyTimer = C4:KillTimer(idBusyTimer) end if (idOperatingStatusQueryTimer) then idOperatingStatusQueryTimer = C4:KillTimer(idOperatingStatusQueryTimer) end if (idStatusQueryTimer) then idStatusQueryTimer = C4:KillTimer(idStatusQueryTimer) end if (idResponseTimeoutTimer) then idResponseTimeoutTimer = C4:KillTimer(idResponseTimeoutTimer) end if (idResponseWaitTimer) then idResponseWaitTimer = C4:KillTimer(idResponseWaitTimer) end if (idPollingTimer) then idPollingTimer = C4:KillTimer(idPollingTimer) end if (gReconnectTimer) then gReconnectTimer = C4:KillTimer(gReconnectTimer) end if (g_VolRampTimerID) then g_VolRampTimerID = C4:KillTimer(g_VolRampTimerID) end if (g_ChannelBufferTimer) then g_ChannelBufferTimer = C4:KillTimer(g_ChannelBufferTimer) endendfunction GetCommandData(strCommand, tParams) --deprecatedendfunction dbg(strDebugText) if (g_debugprint) then print(strDebugText) end if (g_debuglog) then C4:ErrorLog(strDebugText) endendfunction startDebugTimer() if (g_DebugTimer) then g_DebugTimer = C4:KillTimer(g_DebugTimer) end g_DebugTimer = C4:AddTimer(15, 'MINUTES')endfunction fromHex(hexString) -- converts a string representing a hex number to decimal local stringLen = string.len(hexString) local decValue = 0 for k=0,stringLen-1 do lastdigit = string.sub(hexString, stringLen-k) decValue = decValue + (hexmap[lastdigit] * 16^k) hexString=string.sub(hexString,1,stringLen-1) end return decValueendfunction concat_string(s1, s2) if s1 == nil then return s2 else return s1 .. s2 endendfunction changeVolume(lngOutputID, strCommand, strCommandData) lngOutputID=lngOutputID % 1000 if (strCommand == 'STOP_VOL_UP') or (strCommand == 'STOP_VOL_DOWN') then intraCommandDelayValue=g_holdIntraCommandDelayValue if tVolRampTimerID[lngOutputID] ~= nil then C4:KillTimer(tVolRampTimerID[lngOutputID]) tVolRampTimerID[lngOutputID] = nil for j,k in pairs(tEmitCommands) do if string.match(k[1],strCommandData) ~= nil then table.remove(tEmitCommands, j) end end end else if (strCommand == 'START_VOL_UP') or (strCommand == 'START_VOL_DOWN') then g_holdIntraCommandDelayValue=intraCommandDelayValue intraCommandDelayValue=intraVolRampDelayValue if idEmitCommandsTimer ~=nil then C4:KillTimer(idEmitCommandsTimer) idEmitCommandsTimer = nil end if (tVolRampTimerID[lngOutputID] == nil) then if (tVolRampTimerID[lngOutputID]) then tVolRampTimerID[lngOutputID] = C4:KillTimer(tVolRampTimerID[lngOutputID]) end tVolRampTimerID[lngOutputID] = C4:AddTimer(intraVolRampDelayValue, 'MILLISECONDS', true) tVolumeCommands[lngOutputID] = strCommandData tVolumeCommandNames[lngOutputID] = strCommand emit(strCommandData) end else emit(strCommandData) end endendfunction changeChannel(lngOutputID, strCommand, strCommandData) -- Code comments below should be removed when Defect 18784 is fixed (Tuner Proxy continues to send START commands). if (strCommand == 'STOP_CH_UP') or (strCommand == 'STOP_CH_DOWN') then -- C4:KillTimer(ChannelRampTimerID) --Get_Device_State('QUERY_TUNER',{}) else if (strCommand == 'START_CH_UP') or (strCommand == 'START_CH_DOWN') then emit(strCommandData) -- if (ChannelRampTimerID) then -- ChannelRampTimerID = C4:KillTimer(ChannelRampTimerID) -- end -- ChannelRampTimerID = C4:AddTimer(intraCommandDelayValue, 'MILLISECONDS', true) -- ChannelCommands = strCommandData else emit(strCommandData) --Get_Device_State('QUERY_TUNER',{}) end endendfunction CMDS.SET_INPUT(tParams,strCommand) local strCmd = '' local BindingID = 0 local lngOUTPUT = 0 local lngINPUT dbg('SET_INPUT') dbg('SET_INPUT-tParams: ') if tParams ~= nil then for j,k in pairs(tParams) do dbg('SET_INPUT_ParamID: ' .. j .. ' - SET_INPUT_ParamValue: ' .. k) if (j == 'BindingID') then BindingID = k end if (j == 'OUTPUT') then lngOUTPUT = tonumber(k) % 1000 end if (j == 'INPUT') then lngINPUT = tonumber(k) % 1000 end end end strCmd = tInputCommandMap[tInputConnMapByID[lngINPUT].Name] emit(strCmd, strCommand, tParams.OUTPUT) --for RF inputs, send input selection command twice to ensure that TV is on correct input--[[ if (tInputConnMapByID[lngINPUT].Name=='CABLE') or (tInputConnMapByID[lngINPUT].Name=='ANTENNA') then emit(strCmd, strCommand, tParams.OUTPUT) end--]]endfunction CMDS.SET_CHANNEL(tParams,strCommand) dbg('SET_CHANNEL') dbg('SET_CHANNEL-tParams: ') if tParams ~= nil then for j,k in pairs(tParams) do dbg('SET_CHANNEL_ParamID: ' .. j .. ' - SET_CHANNEL_ParamValue: ' .. k) end end local channel, delim, major, minor, strCmd channel = tParams['CHANNEL'] if (channel==nil) or (channel=='') then dbg('SET_CHANNEL ERROR: Channel Param Not Valid [nil]') return end delim = string.find(channel, '%D') if (delim~=nil) then major=string.sub(channel, 1, delim-1) minor=string.sub(channel, delim+1, string.len(channel)) end if (g_DirectChannelTuning=='Analog') then channel = string.rep('0', 3 - string.len(channel)) .. channel strCmd = 'DCCH' .. channel .. ' ' emit(strCmd, strCommand) elseif (g_DirectChannelTuning=='Digital Air') then if (major==nil) then major=channel end if (minor==nil) then minor='00' end major = string.rep('0', 2 - string.len(major)) .. major minor = string.rep('0', 2 - string.len(minor)) .. minor if (string.len(major)>2) then dbg('SET_CHANNEL ERROR: Major Channel Param Not Valid') return end if (string.len(minor)>2) then dbg('SET_CHANNEL ERROR: Minor Channel Param Not Valid') return end strCmd = 'DA2P' .. major .. minor emit(strCmd, strCommand) elseif (g_DirectChannelTuning=='Digital Cable - Two Part') then if (major==nil) then major=channel end if (minor==nil) then minor='000' end major = string.rep('0', 3 - string.len(major)) .. major minor = string.rep('0', 3 - string.len(minor)) .. minor if (string.len(major)>3) then dbg('SET_CHANNEL ERROR: Major Channel Param Not Valid') return end if (string.len(minor)>3) then dbg('SET_CHANNEL ERROR: Minor Channel Param Not Valid') return end strCmd = 'DC2U' .. major .. ' ' emit(strCmd, strCommand .. ' - Major') strCmd = 'DC2L' .. minor .. ' ' emit(strCmd, strCommand .. ' - Minor') elseif (g_DirectChannelTuning=='Digital Cable - One Part') then channel = string.rep('0', 5 - string.len(channel)) .. channel if (string.len(channel)>5) then dbg('SET_CHANNEL ERROR: Channel Param Not Valid [>5]') return end strCmd = 'DC1' .. channel emit(strCmd, strCommand) end --CHANNEL parameter is an INTEGER and cannot support delimeter & minor element if (major~=nil) then C4:SendToProxy(5001,'CHANNEL_CHANGED',{CHANNEL=major}) else C4:SendToProxy(5001,'CHANNEL_CHANGED',{CHANNEL=channel}) endendfunction CMDS.SET_VOLUME_LEVEL(tParams,strCommand) dbg(strCommand) local volume=processVolumeLevel(tParams['LEVEL'], 0, 100, 0, 60) volume= string.rep('0', 2 - string.len(volume)) .. volume local strCmd = 'VOLM' .. volume .. ' ' emit(strCmd, strCommand, tParams.OUTPUT) g_VolumeState = tonumber(volume)endfunction CMDS.START_VOL_DOWN(tParams,strCommand) if (idEmitCommandsTimer~=nil) then C4:KillTimer(idEmitCommandsTimer) idEmitCommandsTimer = nil end g_VolumeRamp='DOWN' if (g_VolRampTimerID==nil) then g_VolRampTimerID=C4:AddTimer(intraVolRampDelayValue, 'MILLISECONDS', true) endendfunction CMDS.START_VOL_UP(tParams,strCommand) if (idEmitCommandsTimer~=nil) then C4:KillTimer(idEmitCommandsTimer) idEmitCommandsTimer = nil end g_VolumeRamp='UP' if (g_VolRampTimerID==nil) then g_VolRampTimerID=C4:AddTimer(intraVolRampDelayValue, 'MILLISECONDS', true) endendfunction CMDS.STOP_VOL_UP(tParams,strCommand) g_VolumeRamp='' emit(CMDS.QUERY_VOLUME_STATE,'QUERY_VOLUME_STATE') if (g_VolRampTimerID~=nil) then C4:KillTimer(g_VolRampTimerID) g_VolRampTimerID=nil end if (tEmitCommands[1]~=nil) then if (idEmitCommandsTimer==nil) then idEmitCommandsTimer = C4:AddTimer(intraCommandDelayValue, 'MILLISECONDS', true) end endendfunction CMDS.STOP_VOL_DOWN(tParams,strCommand) g_VolumeRamp='' emit(CMDS.QUERY_VOLUME_STATE,'QUERY_VOLUME_STATE') if (g_VolRampTimerID~=nil) then C4:KillTimer(g_VolRampTimerID) g_VolRampTimerID=nil end if (tEmitCommands[1]~=nil) then if (idEmitCommandsTimer==nil) then idEmitCommandsTimer = C4:AddTimer(intraCommandDelayValue, 'MILLISECONDS', true) end endendfunction processVolumeLevel(volLevel, minVolLevel, maxVolLevel, minDeviceLevel, maxDeviceLevel) local level = (volLevel-minVolLevel)/(maxVolLevel-minVolLevel) local vl=(level*(maxDeviceLevel-minDeviceLevel))+minDeviceLevel vl= tonumber(("%.".."0".."f"):format(vl)) dbg('processVolumeLevel: level in=' .. volLevel .. ', level out=' .. vl) return vlendfunction CMDS.LUA_ACTION(tParams,strCommand) if tParams ~= nil then for cmd,cmdv in pairs(tParams) do dbg(cmd,cmdv) if cmd == 'ACTION' then if cmdv == 'Destroy Timers' then OnDriverDestroyed() elseif CMDS[cmdv] ~= nil then emit(CMDS[cmdv], cmdv) else dbg('From ExecuteCommand Function - Undefined Action') dbg('Key: ' .. cmd .. ' Value: ' .. cmdv) end else dbg('From ExecuteCommand Function - Undefined Command') dbg('Key: ' .. cmd .. ' Value: ' .. cmdv) end end endendfunction send_polling() if (bPowerOnSequence==true) then return end if g_VolumeRamping then return end if (g_ChannelBufferTimer ~= nil) then return end emit('POWR? ', 'QUERY POWER') if (g_PowerState == 'OFF') then return end emit('IAVD? ', 'QUERY INPUT') emit('VOLM0? ', 'QUERY VOLUME') emit('MUTE? ', 'QUERY MUTE')endfunction CMDS.NUMBER_1(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_2(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_3(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_4(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_5(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_6(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_7(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_8(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_9(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.NUMBER_0(tParams,strCommand) processDigits(string.sub(strCommand,8))endfunction CMDS.POUND(tParams,strCommand) processDigits('-')endfunction CMDS.ENTER(tParams,strCommand) if g_ChannelBuffer ~= nil then local channel=g_ChannelBuffer g_ChannelBuffer=nil CMDS.SET_CHANNEL({['CHANNEL']=channel,},'SET_CHANNEL') if g_ChannelBufferTimer ~= nil then g_ChannelBufferTimer = C4:KillTimer(g_ChannelBufferTimer) g_ChannelBufferTimer=nil end else emit('RCKY40 ','ENTER') end endfunction CMDS.CANCEL(tParams,strCommand) if g_ChannelBufferTimer ~= nil then g_ChannelBufferTimer = C4:KillTimer(g_ChannelBufferTimer) g_ChannelBufferTimer=nil else emit('RCKY46 ','CANCEL') end g_ChannelBuffer=nilendfunction processDigits(digit) if g_ChannelBuffer==nil then if (digit~='-') then g_ChannelBuffer=digit end else g_ChannelBuffer=g_ChannelBuffer .. digit end if (g_ChannelBufferTimer == nil) then g_ChannelBufferTimer = C4:AddTimer(g_ChannelBufferTimerValue, 'SECONDS', false) endend]]></script> </config> <driverdocumentation> <category name="certified" description="Certification">Control4 certified on 5/25/2011 for software released versions: 1.8.2, 2.1.0.</category> </driverdocumentation> <controlmethod>ip</controlmethod></devicedata> Link to comment Share on other sites More sharing options...
ILoveC4 Posted June 2, 2013 Author Share Posted June 2, 2013 In looking at it here I think I have it figured out.I'll check. Link to comment Share on other sites More sharing options...
brente Posted June 2, 2013 Share Posted June 2, 2013 As a quick response, I believe that if you want to add a simple output command, you need to do the following:- add an entry to the "commands" section so that you can invoke a 'command' under program control- add a command to the CMDS list that has the same name as the above commandif the device/driver is already in the project, you (unfortunately) have to delete the device from the project, then re-add it... Link to comment Share on other sites More sharing options...
k1993 Posted April 5, 2018 Share Posted April 5, 2018 i new for driver development ...I got this errors. "The class name must match the the proxy name". any one have answer Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.