class Buttplug::Client
Our Client
for a buttplug.io server
Public Class Methods
Creates a new client for buttplug.io
Arguments:
-
serverLocation (string) - Where our buttplug.io server is hosted. this will tend to be:
"wss://localhost:12345/buttplug"
Returns:
-
A shiney new buttplug client ready for some action
# File lib/buttplugrb.rb, line 34 def initialize(serverLocation, clientName="buttplugrb") @messageID=1 @location=serverLocation #Ok Explanation time! # * @EventQueue - The events we are triggering on the server, Expected to be an array, with the first element being the message Id, and the second being the message itself! @eventQueue=EM::Queue.new @logLevel=Buttplug::LogLevel::Off @scanning=false @currentDevices=[]; startEventMachine() @eventMachine.run end
Public Instance Methods
# File lib/buttplugrb.rb, line 122 def currentDevices() return @currentDevices end
# File lib/buttplugrb.rb, line 125 def deviceSusbscribe(id,&code) #TODO: Add Code here to allow a class like Buttplug::Device to subscribe to events, annnnd realize that the device has disconnected when that does happen (like the hush has a tendeancy to do ... ) end
Does exactly what it says on the tin, generates a random id for our messages
Returns:
-
a number between 2 and 4294967295
# File lib/buttplugrb.rb, line 118 def generateID() @messageID+=1 return @messageID end
# File lib/buttplugrb.rb, line 66 def isScanning?() return @scanning end
Lists all devices available to the server
Returns:
-
An array of available devices from the server
Example:
client.listDevices() [{"DeviceName"=>"XBox Compatible Gamepad (XInput)", "DeviceIndex"=>1, "DeviceMessages"=>{"SingleMotorVibrateCmd"=>{}, "VibrateCmd"=>{"FeatureCount"=>2}, "StopDeviceCmd"=>{}}}]
end ¶ ↑
# File lib/buttplugrb.rb, line 79 def listDevices() id=generateID() deviceRequest=[id,"[{\"RequestDeviceList\": {\"Id\":#{id}}}]"] @eventQueue.push(deviceRequest) while(deviceRequest.length<3) do sleep 0.01#Just so we arn't occupying all the time on the system while we are waiting for our device list to come back. end return deviceRequest[2]["DeviceList"]["Devices"] end
Sends a message to our buttplug server
Arguments:
-
message (JSON formatted string) - The message we are sending to our server
Returns:
-
the Response from our server
# File lib/buttplugrb.rb, line 105 def sendMessage(message) @eventQueue.push(message) while(message.length<3) do sleep 0.01 end return message[3] end
# File lib/buttplugrb.rb, line 46 def setLogLevel(logLevel) @logLevel=logLevel end
Tells our server to start scanning for new devices
# File lib/buttplugrb.rb, line 52 def startScanning() id=generateID() response=sendMessage([id,"[{\"StartScanning\":{\"Id\":#{id}}}]"]) if(response[0].keys.include? "Error") #TODO: Add Error Handling code end end
Stops all devices currently controlled by the server
# File lib/buttplugrb.rb, line 91 def stopAllDevices() id=generateID() deviceRequest=[id,"[{\"StopAllDevices\": {\"ID\":#{id}}}]"] @eventQueue.push(deviceRequest) end
Tells our server to stop scanning for new devices
# File lib/buttplugrb.rb, line 62 def stopScanning() id=generateID() @eventQueue.push([id,"[{\"StopScanning\":{\"Id\":#{id}}}]"]) end
Protected Instance Methods
# File lib/buttplugrb.rb, line 129 def startEventMachine() @eventMachine=Thread.new{EM.run{ eventQueue=@eventQueue messageWatch={} logLevel=@logLevel scanning=@scanning currentDevices=@currentDevices ws = Faye::WebSocket::Client.new(@location) tickLoop=EM.tick_loop do #Should improve response times~ eventQueue.pop{|msg| ws.send msg[1] messageWatch[msg[0]]=msg p [Time.now, :message_send, msg[1]] } end ws.on :open do |event| p [Time.now, :open] ws.send "[{\"RequestServerInfo\": {\"Id\": 1, \"ClientName\": \"#{clientName}\", \"MessageVersion\": 1}}]" #TODO: Add MaxPingTime Code end ws.on :message do |event| #Ok, first of all let's grab message=JSON::parse(event.data).each{|event| message.each{|key,value| #We don't really care about the key just yet ... We are going to just care about finding our ID if(messageWatch.keys.include?(value["Id"])) messageWatch[value["Id"]]<<{key => value}#And now we care about our key! puts messageWatch[value["Id"]].object_id messageWatch.delete(value["Id"]) p [Time.now, :message_recieved, [{key => value}]] next #If we are currently scanning, we should Probably check and see if we recieved a ScanningFinished message elsif(scanning&&key=="ScanningFinished") p [Time.now,:ScanningFinished] scanning=false #If we are logging, we should probably Check and see if this is a log ... elsif(logLevel>Buttplug::LogLevel::Off&&key=="Log") p [Time.now,:ServerLog,value] #and last but not least if we spot our server info we should probably log it ... elsif(key=="DeviceAdded") #Oh? Sweet let's go ahead and add it's information to our array! currentDevices.push( {"DeviceName" => value["DeviceName"], "DeviceIndex" => value["DeviceIndex"], "DeviceMessages" => value["DeviceMessages"]}) elsif(key=="DeviceRemoved") #well darn, and to just have compatability with the current js version of buttplug.io we are gonna do this a bit diffrently than I'd like ... we are totally not doing this because I'm feeling lazy and want to push out this itteration, no sir currentDevices.reject!{|device| device["Id"]==value["Id"] } elsif(key=="ServerInfo") p [Time.now, :server_info, value] end } } end ws.on :close do |event| p [Time.now, :close, event.code, event.reason] ws = nil #TODO: Add Nil checks for Sends, and Nil out the ping when closed end EM.add_periodic_timer(0.5){ ws.send "[{\"Ping\": {\"Id\": #{generateID()}}}]" } #TODO: Add Error code https://metafetish.github.io/buttplug/status.html#error #So, I should probably add some basic error handling to most of the code then ... #TODO: Add Log code https://metafetish.github.io/buttplug/status.html#requestlog #Done, I think ... please correct me if I'm wrong }} end