buttplugio / buttplug-py Goto Github PK
View Code? Open in Web Editor NEWPython implementation of core message system and client for the Buttplug Sex Toy Protocol Standard
Home Page: https://buttplug-py.docs.buttplug.io
License: Other
Python implementation of core message system and client for the Buttplug Sex Toy Protocol Standard
Home Page: https://buttplug-py.docs.buttplug.io
License: Other
No matter what name I set for the client (client = ButtplugClient("Something")
), in intiface it's always displayed as "Client Test".
I need to pull the devices list and their features and names from the client.devices object. However, due to how the dict is structured, it is complex to work with it. It'd be very useful to get a quick json that shows the needed information.
Devices with multiple motors will not vibrate as expected when using send_vibrate_cmd(float)
. Instead, only the first motor of that device will vibrate.
Steps to reproduce:
send_vibrate_cmd(1.0)
on that device.Expected behavior:
All motors will vibrate with the same intensity.
It appears to be because Line 255 of buttplug/client/client.py only sets the speed of the motor at index 0 and does not consider devices with multiple motors.
Workaround: Multiplying a list by the number of motors:
e.g.
vibratorCount = dev.allowed_messages["VibrateCmd"].feature_count
intensity = [1.0] * vibratorCount
await dev.send_vibrate_cmd(intensity)
I don't know rust language
Do I need to compile rust source code?
Where is the executable file of the server ?
Epic for issues relating to releasing a full v1 of buttplug-py.
v1 is a client only release (no plans to release a python buttplug server). It should be able to connect to Intiface Desktop/CLI instances, through either websockets or IPC. These connectors may come as external packages since multiple websocket solutions exist.
When client.device_removed_handler += device_removed
is called, the error below is thrown.
DeviceRemoved(device_index=0)
Task exception was never retrieved
future: <Task finished coro=<ButtplugClientWebsocketConnector._consumer_handler() done, defined at /usr/local/lib/python3.7/dist-packages/buttplug/client/websocket_connector.py:24> exception=AttributeError("'dict' object has no attribute 'remove'") created at /usr/lib/python3.7/asyncio/tasks.py:325>
source_traceback: Object created at (most recent call last):
File "Buttplug_Example.py", line 186, in
asyncio.run(main(), debug=True)
File "/usr/lib/python3.7/asyncio/runners.py", line 43, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.7/asyncio/base_events.py", line 571, in run_until_complete
self.run_forever()
File "/usr/lib/python3.7/asyncio/base_events.py", line 539, in run_forever
self._run_once()
File "/usr/lib/python3.7/asyncio/base_events.py", line 1767, in _run_once
handle._run()
File "/usr/lib/python3.7/asyncio/events.py", line 88, in _run
self._context.run(self._callback, *self._args)
File "Buttplug_Example.py", line 44, in try_connect
await client.connect(connector)
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/client.py", line 85, in connect
await self.connector.connect()
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/websocket_connector.py", line 22, in connect
asyncio.create_task(self._consumer_handler())
File "/usr/lib/python3.7/asyncio/tasks.py", line 325, in create_task
return loop.create_task(coro)
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/websocket_connector.py", line 37, in _consumer_handler
await self._notify_observers(bp_msg)
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/connector.py", line 52, in _notify_observers
await obs._handle_message(msg)
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/client.py", line 176, in _handle_message
await self._parse_message(msg)
File "/usr/local/lib/python3.7/dist-packages/buttplug/client/client.py", line 144, in _parse_message
self.devices.remove(dr.device_index)
AttributeError: 'dict' object has no attribute 'remove
`
Your ButtplugClient.device_added_handler
takes a ButtplugClientDevice
as a param (link), and the ButtplugClient.device_removed_handler
takes an int
(link) referring to the device's index. It makes more sense to me personally for it to take a ButtplugClientDevice
both times.
This would be a breaking change, but to me it makes more sense than right now. Please do say if you did this deliberately.
Hello, I tried to wrap the examples/example.py in a thread as suggested to be able to use this library in a synchronous project.
I'm new to Python and it doesn't work. Can someone please have a look on this and/or add an example to the repository?
from buttplug.client import (ButtplugClientWebsocketConnector, ButtplugClient,
ButtplugClientDevice, ButtplugClientConnectorError)
from buttplug.core import ButtplugLogLevel
import asyncio
import threading
import time
from queue import Queue
class ButtplugConnectorThread(threading.Thread):
def __init__(self, queue, args=(), kwargs=None):
threading.Thread.__init__(self, args=(), kwargs=None)
self.queue = queue
self.daemon = True
def run(self):
self.buttplug_connector = asyncio.run(ButtplugConnector.create())
while True:
val = self.queue.get()
if val is None:
return
self.message_received(val)
def message_received(self, message):
print("Received {}".format(message))
self.buttplug_connector.set_vibration(message)
class ButtplugConnector:
@classmethod
async def create(cls):
self = ButtplugConnector()
self.client = ButtplugClient("Something")
self.connector = ButtplugClientWebsocketConnector("ws://127.0.0.1:12345")
self.devices = []
await self.connect()
return self
async def connect(self):
self.client.device_added_handler += self.device_added
try:
await self.client.connect(self.connector)
await self.client.request_log('Debug')
except ButtplugClientConnectorError as e:
print("Could not connect to Intiface: {}".format(e.message))
return
await self.client.start_scanning()
async def set_vibration(self, value):
for device in self.devices:
await device.send_vibrate_cmd(value)
async def device_added_task(self, dev: ButtplugClientDevice):
self.devices.append(dev)
print("Device Added: {}".format(dev.name))
def device_added(self, emitter, dev: ButtplugClientDevice):
asyncio.create_task(self.device_added_task(dev))
async def disconnect(self):
try:
await self.client.stop_scanning()
await self.client.disconnect()
except:
pass
buttplug_thread = ButtplugConnectorThread(Queue())
buttplug_thread.start()
buttplug_thread.queue.put(0.5)
while True:
time.sleep(100)
pass
It connects but it disconnects right away.
There's currently no way to handle a connection closed that I am aware of. Especially when receiving the below:
code = 1006 (connection closed abnormally [internal]), no reason
This could totally be my poor knowledge of asyncio but it seems like we need an event in those situations.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.