Created
October 17, 2023 21:28
-
-
Save bananasov/89831d116b8b5655e00c76b4a18dab16 to your computer and use it in GitHub Desktop.
Buttplug.io connection for CC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- buttplug.lua | |
-- | |
-- MIT License | |
-- | |
-- Copyright (c) 2021 abbiwyn | |
-- | |
-- Permission is hereby granted, free of charge, to any person obtaining a copy | |
-- of this software and associated documentation files (the "Software"), to deal | |
-- in the Software without restriction, including without limitation the rights | |
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
-- copies of the Software, and to permit persons to whom the Software is | |
-- furnished to do so, subject to the following conditions: | |
-- | |
-- The above copyright notice and this permission notice shall be included in all | |
-- copies or substantial portions of the Software. | |
-- | |
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
-- SOFTWARE. | |
local messages = { | |
-- Status messages | |
Ok = { | |
Ok = { | |
Id = 1 | |
} | |
}, | |
Error = { | |
Error = { | |
Id = 0, | |
ErrorMessage = "", | |
ErrorCode = 0 | |
} | |
}, | |
-- Handshake messages | |
RequestServerInfo = { | |
RequestServerInfo = { | |
Id = 1, | |
ClientName = "", | |
MessageVersion = 1 | |
} | |
}, | |
ServerInfo = { | |
ServerInfo = { | |
Id = 1, | |
ServerName = "", | |
MessageVersion = 1, | |
MaxPingTime = 0 | |
} | |
}, | |
-- Enumeration messages | |
RequestDeviceList = { | |
RequestDeviceList = { | |
Id = 1 | |
} | |
}, | |
DeviceList = { | |
DeviceList = { | |
Id = 1, | |
Devices = {} | |
} | |
}, | |
StartScanning = { | |
StartScanning = { | |
Id = 1 | |
} | |
}, | |
StopScanning = { | |
StopScanning = { | |
Id = 1 | |
} | |
}, | |
ScanningFinished = { | |
ScanningFinished = { | |
Id = 0 | |
} | |
}, | |
DeviceAdded = { | |
DeviceAdded = { | |
Id = 0, | |
DeviceName = "", | |
DeviceIndex = 0, | |
DeviceMessages = {} | |
} | |
}, | |
DeviceRemoved = { | |
DeviceRemoved = { | |
Id = 0, | |
DeviceIndex = 0 | |
} | |
}, | |
-- Generic device messages | |
StopDeviceCmd = { | |
StopDeviceCmd = { | |
Id = 1, | |
DeviceIndex = 0 | |
} | |
}, | |
StopAllDevices = { | |
StopAllDevices = { | |
Id = 1 | |
} | |
}, | |
VibrateCmd = { | |
VibrateCmd = { | |
Id = 1, | |
DeviceIndex = 0, | |
Speeds = {} | |
} | |
} | |
} | |
-- | |
-- Client | |
-- | |
local buttplug = { | |
msg_counter = 1, | |
devices = {}, | |
print = print, -- User can override this w/ game print function | |
-- Callbacks to run when receiving messages from the server | |
callbacks = { | |
Ok = {}, | |
Error = {}, | |
ServerInfo = {}, | |
DeviceList = {}, | |
DeviceAdded = {}, | |
DeviceRemoved = {}, | |
ScanningFinished = {} | |
} | |
} | |
local function run_callbacks(message_type) | |
for k, f in pairs(buttplug.callbacks[message_type]) do | |
f() | |
end | |
end | |
local function message_type(msg) | |
-- Message type is the first field | |
return next(msg) | |
end | |
-- Send a message to the Buttplug Server | |
local function send(msg) | |
local message_type = message_type(msg) | |
-- Set message ID num and increment counter | |
msg[message_type].Id = buttplug.msg_counter | |
buttplug.msg_counter = buttplug.msg_counter + 1 | |
local payload = "[" .. textutils.serializeJSON(msg) .. "]" | |
buttplug.print("> " .. payload) | |
return buttplug.sock.send(payload) | |
end | |
function buttplug.request_server_info(client_name) | |
local msg = messages.RequestServerInfo | |
msg["RequestServerInfo"]["ClientName"] = client_name | |
return send(msg) | |
end | |
function buttplug.request_device_list() | |
return send(messages.RequestDeviceList) | |
end | |
function buttplug.start_scanning() | |
return send(messages.StartScanning) | |
end | |
function buttplug.stop_scanning() | |
return send(messages.StopScanning) | |
end | |
-- Sends a vibrate command to device with the index `dev_index`. | |
-- `speeds` is a table with 1 vibration value per motor e.g. { 0.2, 0.2 | |
-- } would set both motors on a device with 2 motors to 0.2 | |
function buttplug.send_vibrate_cmd(dev_index, speeds) | |
local msg = messages.VibrateCmd | |
msg["VibrateCmd"]["DeviceIndex"] = dev_index | |
for i, v in ipairs(speeds) do | |
msg["VibrateCmd"]["Speeds"][i] = { Index = i - 1, Speed = v } | |
end | |
return send(msg) | |
end | |
function buttplug.send_stop_device_cmd(dev_index) | |
local msg = messages.StopDeviceCmd | |
msg["StopDeviceCmd"]["DeviceIndex"] = dev_index | |
return send(msg) | |
end | |
function buttplug.send_stop_all_devices_cmd() | |
return send(messages.StopAllDevices) | |
end | |
function buttplug.count_devices() | |
return table.getn(buttplug.devices) | |
end | |
function buttplug.add_device(dev) | |
local dev_count = table.getn(buttplug.devices) | |
buttplug.devices[dev_count + 1] = { | |
index = dev["DeviceIndex"], | |
name = dev["DeviceName"], | |
messages = dev["DeviceMessages"] | |
} | |
end | |
function buttplug.remove_device(dev_index) | |
for i, v in ipairs(buttplug.devices) do | |
if v.index == dev_index then | |
table.remove(buttplug.devices, i) | |
end | |
end | |
end | |
-- Decide what to do based on the message type | |
function buttplug.handle_message(raw_message) | |
local msg = textutils.unserializeJSON(raw_message)[1] | |
local msg_type = message_type(msg) | |
local msg_contents = msg[msg_type] | |
-- if DeviceList, add any devices | |
if (msg_type == "DeviceList") then | |
local devices = msg_contents["Devices"] | |
for i, v in ipairs(devices) do | |
buttplug.add_device(v) | |
end | |
end | |
-- if DeviceAdded, add the device | |
if (msg_type == "DeviceAdded") then | |
buttplug.add_device(msg_contents) | |
end | |
-- if DeviceRemoved, remove the device | |
if (msg_type == "DeviceRemoved") then | |
buttplug.remove_device(msg_contents["DeviceIndex"]) | |
end | |
-- Run callbacks for the message | |
run_callbacks(msg_type) | |
end | |
-- Gets and handles messages from the server. Returns the message when | |
-- something goes wrong | |
function buttplug.get_and_handle_message() | |
local event, url, message = os.pullEvent("websocket_message") | |
-- Error checking grrr | |
-- if not happy then | |
-- return message | |
-- end | |
-- Intiface will send just a newline char if it has no messages, so | |
-- check for that | |
if message and string.len(message) > 1 then | |
buttplug.print("< " .. message) | |
buttplug.handle_message(message) | |
end | |
end | |
-- Open the socket and send a handshake message to the server | |
function buttplug.connect(client_name, ws_addr) | |
buttplug.client_name = client_name | |
buttplug.sock = http.websocket(ws_addr) | |
buttplug.request_server_info(buttplug.client_name) | |
end | |
return buttplug |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment