PDA

View Full Version : Help!! Serial device



Manser
March 26th, 2009, 12:48 AM
I set up a serial device for a bose dsp!

I poll all slots and channels of the bose.
this works great. Poll interval is 30ms, parser timeout is 20ms, noResponseTimout 25ms.
I stop polling when I send commands from girder.
All this works great. But it fills me up the queue with commands which is possible.
the problem now is that if once the queue is full it just stop sending any commands.

Log looks then:
OnQueueFull: 100
OnQueueFull: 100
OnQueueFull: 100
OnQueueFull: 100

How can I manage that:

OnQueueFull = function(self)
self.Transport:ClearQueue()
print("Reset durch Bose ESP88")
gir.TriggerEventEx("Reset", 18, 0, 0)
end,

ClearQueue() does not help, all I can do is a script reset!
But there must be a better way to handle this!!!


-[[

Bose ESP88

--]]

local Super = require('transport.Base')
local prepare = require('transport.PrepareSettings')
local constants = require('transport.constants')
local table = require('table')
local print = print
local math = require('math')
local gir = require("gir")
local string = string


module("transport.devices.BoseESP88")


local DefaultSettings = prepare(

{
Transport = {
Post = {
NoResponseTimeout = 25,
},
},
Parser = {
Type = constants.parser.TERMINATED,
Terminator = '\r',
Timeout = 20,
},
MaxQueuedItems = 100,
},

{
Transport = {
Post = {
Baud = 38400,
Flow = 'N',
Parity = 'N',
DataBits = 8,
StopBits = 1,
},
},
}
)


local Object = Super:Subclass ( {

Name = 'Bose ESP88',

Description = [[<b>Bose ESP88</b><br>
<color=#444444>Bose Serial Driver by Manser Bild- und Tonkonzepte GmbH </color>]],

GUIDefaults = {
allowedtransports = {
[constants.transport.GIP] = false,
[constants.transport.SERIAL] = true,
},
defaulttransport = constants.transport.GIP,
hostname = "192.168.1.70",
port = 4998,
},

GetSettings = function ( self )
return table.copy(DefaultSettings[self.TransportType])
end,

--GetConsoleLogLevel = function(self)
-- return 0 -- temporary 0 = alles
--end,

OnQueueFull = function(self)
self.Transport:ClearQueue()
print("Reset durch Bose ESP88")
gir.TriggerEventEx("Reset", 18, 0, 0)
end,


OnDisconnected = function(self)

end,

OnConnectFailed = function ( self )
print(self.Name .. ": Connect Failed")
end,

OnBuildCommand = function (self, data )
return data ..'\r'
end,

OnReceiveData = function(self, Event)
--print(self.Name .. " Received: " .. Event:GetData())

local empfang = Event:GetData()
if string.sub(empfang,1,2) == "GM" then
gir.TriggerEventEx("Mute_Daten", 18, 0, Event:GetData())
end
if string.sub(empfang,1,2) == "GV" then
gir.TriggerEventEx("Vol_Daten", 18, 0, Event:GetData())
end
if string.sub(empfang,1,2) == "GL" then
gir.TriggerEventEx("Sig_Daten", 18, 0, Event:GetData())
end
if string.sub(empfang,1,2) == "GN" then
gir.TriggerEventEx("Mute_Group_Daten", 18, 0, Event:GetData())
end
if string.sub(empfang,1,2) == "GG" then
gir.TriggerEventEx("Vol_Group_Daten", 18, 0, Event:GetData())
end
end,

} )


Name = Object.Name
Description = Object.Description
GUIDefaults = Object.GUIDefaults

function New (self,settings)
return Object:New(settings)
end




The solution could probably be just not to queue any command - But How?

Rob H
March 26th, 2009, 01:23 AM
How are you polling it? 30ms sounds a bit often to me, that's a window of about 100 characters, but you also have to take into account the amount of time it takes to process the data in OnReceiveData.

self.Transport:ClearQueue() should empty the queue however

Manser
March 26th, 2009, 01:34 AM
With a simple timer?

It works, it works as well with 15 ms ;-)
If I just poll it, it runs for weeks!


the fast poll is because I have to read from different slots and channels
the level, the state, the signal level. 10slots every have 4 channels!


but you also have to take into account the amount of time it takes to process the data in OnReceiveData.

But that should not affect the serial device??

The solution could probably be just not to queue any command - But How?
Is this possible?

Rob H
March 26th, 2009, 01:54 AM
Okay, so you're sending commands to it as well and that causes a problem right?

So what's the code that sends commands?

How soon after sending a command do you resume polling?

You may want to implement a handler for OnQueued(position, command) so you can keep track of the size of the queue, that should give you a better idea of how many commands are waiting and when it starts to rise.

Manser
March 26th, 2009, 02:03 AM
Yes that's right:

thats the code which is poll the device values:
fired from a simple timer:


-- Hier Anzahl der Slots und Groups Einstellen
local max_slots = 5
local max_groups = 1

--Aufruf des Comhandlers
local c = ComponentManager:GetComponentUsingName("Transport Manager")
local bose = c:GetTransportUsingName("My Bose ESP88")

----------------------------------------------------------------------
-------------------------Slotsabfragen--------------------------------
----------------------------------------------------------------------
--Abfrage Mute Slots
local sendstring
local sendstring1 = "GM"

function bose_mute_poll()

if slots_M <= max_slots then
sendstring = sendstring1 .. slots_M .. "," .. channel_M
bose:Send(sendstring)
if channel_M >= 4 then
channel_M=1
slots_M = slots_M + 1
else
channel_M = channel_M + 1
end

if slots_M > max_slots then
slots_M = 1
end
end
end


----------------------------------------------------------------------
-------------------------Pollrhythmus---------------------------------
----------------------------------------------------------------------
if bose_pollstoper == 0 then
if bose_pollcounter == 1 then
bose_vol_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 2 then
bose_sig_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 3 then
bose_vol_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 4 then
bose_sig_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 5 then
bose_group_vol_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 6 then
bose_group_mute_poll()
bose_pollcounter = bose_pollcounter + 1
elseif bose_pollcounter == 7 then
bose_mute_poll()
bose_pollcounter = 1
end
end


And that's the code if I send a command for changing somthing Here the mute state:

It's starts a timer which first stop the poll and then send the command and aktivate the pollmode at the end


---**************Senden mute slots***********************************
---20.03.09 SL
---************************************************** **********************

--daten aus multiroom
local data = tonumber(pld3)

--Aufruf des Comhandlers
local c = ComponentManager:GetComponentUsingName("Transport Manager")
local bose = c:GetTransportUsingName("My Bose ESP88")

--senden aufbereiten
local sendstring = "SN" .. data .. "," .. ",T"


local counter = 1

function Mute_send_group()

if counter == 1 then
bose_pollstoper = 1
counter = counter + 1
elseif counter == 2 then
bose:Send(sendstring)
counter = counter + 1
elseif counter >= 3 then
bose_pollstoper = 0
Mute_Timer_group:Destroy()
Mute_Timer_group = nil
counter = 1
end

end

Mute_Timer_group = gir.CreateTimer("","Mute_send_group()","")
Mute_Timer_group:Arm(30) --50

Manser
March 26th, 2009, 02:19 AM
OnQueued(position, "command")

"command" is a function I can add in the serial device or what?

Manser
March 26th, 2009, 05:44 AM
Switched back to the old serial class, there it works like a charm.
Perfect.

We have to look once where the problem is in the new transport class.
I would really like to use them.

if you like I can send you this project. I have it for both the old serial class and the new transport class

Thanks for your support Rob

Rob H
March 26th, 2009, 09:29 AM
OnQueued(position, "command")

"command" is a function I can add in the serial device or what?


No, that is just called every time a new command is added to the queue. command is a table that describes the text to send. The interesting parameter there for your purposes at the moment is position. That will tell you when the queue starts to fill up.