pygame-menu not working with posted events - pygame

I want to use pygame-menu on a raspberry pi with rotary encoders. When I post up/down events from the encoder callback to pygame, it does not seem compatible. The menu does not react. The same code can post non-keyup/down events successfully. For example:
pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'unicode': '', 'key': 274, 'mod': 0, 'scancode': 108})) # no menu movement
pygame.event.post(pygame.event.Event(pygame.QUIT, {})) # works as expected
Is there a way to simulate keyboard events that can operate the menu?
pygame is at 1.9.6, pygame-menu is 4.1.6

As revealed in https://github.com/ppizarror/pygame-menu/issues/359 pygame checks every key event if there's a corresponding keypress. Drops the event if no match found. The logic can be bypassed with the test=True attribute, as demonstrated in the pygame-menu unit test cases. The following modification allows the proper keydown event injection:
pygame.event.post(pygame.event.Event(pygame.KEYDOWN, {'unicode': '', 'key': 274, 'mod': 0, 'scancode': 108, 'test': True}))

Related

Why need to return a function in Reagent component?

From the Reagent introduction, a simple timer component:
(defn timer-component []
(let [seconds-elapsed (r/atom 0)]
(fn []
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:div
"Seconds Elapsed: " #seconds-elapsed])))
and below it reads
The previous example also uses another feature of Reagent: a component
function can return another function, that is used to do the actual
rendering. This function is called with the same arguments as the
first one.
This allows you to perform some setup of newly created components
without resorting to React’s lifecycle events.
Can someone remind me of the underlying principle here? Why do we need this anonymous function? Why not just
(defn timer-component []
(let [seconds-elapsed (r/atom 0)]
(js/setTimeout #(swap! seconds-elapsed inc) 1000)
[:div
"Seconds Elapsed: " #seconds-elapsed])))
From what I remember, Reagent calls timer-component every time it wants to render - potentially setting up the same piece of state (seconds-elapsed) over and over again.
By returning that anonymous function instead, it tells Reagent "use this to render timer-component". This way your state setup is separated from rendering, and like your doco quote says, its a way to perform state setup without using Reacts lifecycle events.
Hope that makes sense
Tl;dr: The anonymous function that is returned is the render method, which every component must have. You can elide the anonymous function if you use the with-let macro in Reagent.
The indispensable part of a React component is a render function, which takes a single object argument and returns a React element. The difference between render
and the component constructor is that, while both methods are called upon construction, render is called on each update. (For instance, if someone calls the setState method of the component).
In the above example, the difference between the inner, anonymous function and the outer timer-component function is the same as between render and the constructor. Notice that the anonymous function closes over the variables bound in the let clause, which allows it to be stateful. If timer-component itself were the render function, then it would be called on every update, and seconds-elapsed would be endlessly reset to zero.
See the doc on the Reagent repo called "Creating Reagent Components".

Why is db printing #object[Object [object Object]] in reframe?

In the following code I'm dispatching two on-click events:
;; event
(reg-event-db
:some
(fn [db [_ some-val]]
(prn "The db is" db)
(assoc db :some some-val)
))
;; another event
(reg-event-db
:another
(fn [db [_ another-val]]
(prn "The db is" db)
(assoc db :another another-val)
))
;; button
[:input {:type "button" :value "Button"
:on-click #(do
(dispatch [:some :some-val])
(dispatch [:another :another-val]))}]
But instead of printing the db map, it prints "The db is" #object[Object [object Object]], and then
Error: No protocol method IAssociative.-assoc defined for type object: [object Object]
What am I doing wrong? I also tried doing #(dispatch [:some :some-val :another another-val] but that gave the same error. In general, how to correctly dispatch two events?
This is correct:
(do
(dispatch [:first-event :some-value])
(dispatch [:second-event :other-value]))
This is not correct:
(dispatch [:some :some-val :another another-val])
In this example, you are dispatching one event with 3 arguments:
:some is the event name,
:some-val is the first argument,
:another is the second argument,
another-val is the 3rd argument.
The error you are encountering doesn't come from the way you dispatch events, but rather from your db state. Let's dissect it step by step:
If (prn db) outputs #object[Object [object Object]] it means db is a JavaScript object.
If (assoc db …) fails with No protocol method IAssociative.-assoc defined for type object: [object Object], it means the db value does not support the assoc function. The assoc function is defined by a protocol (think interface) and this protocol is implemented on maps. So here, db is not a map.
Why would db be a JavaScript object instead of a Clojure map?
When you use (reg-event-db :event-name handler-function), the value returned by handler-function will replace the db state. If by mistake you return a JS object, it will become the new db value, and this new incorrect db value will get passed to subsequent event handlers. So it's highly probable that one of your event handlers is returning a JavaScript object.
How I would solve this situation:
use (js/console.log db) instead of (prn db). You'll be able to see what's inside this js object. prn doesn't know how to print js objects properly.
make sure cljs-devtools is installed and running. It allows you to explore complex objects in the console. Next time this issue arises, you'll immediately see what's the problematic value instead of an opaque string representation.
use reg-event-fx instead of reg-event-db. While a little bit more verbose, it will make more explicit to the human eye what value you are putting in db.
if you want to go further and ensure this never happens again, take a look at Re-Frame Middlewares. In your case, middlewares would allow you to act on handlers returned values, and potentially reject it if it doesn't match your expectations.

how to use the recognized text with Google Assistant's hotword.py code

How do I get the spoken text from the hotword.py code & do my own actions on the recognised text rather than Google going off and reacting to the text?
I've installed GA on the Pi3 & after some initial issues with usb mic/analogue audio settings and certain Python files missing this got me going:
When installing Google Assistant, I an error "...googlesamples.assistant' is a package and cannot be directly executed..."
I then followed the Google Next steps : https://developers.google.com/assistant/sdk/prototype/getting-started-pi-python/run-sample and created a new project "myga/" with a hotword.py file that contains:
def process_event(event):
"""Pretty prints events.
Prints all events that occur with two spaces between each new
conversation and a single space between turns of a conversation.
Args:
event(event.Event): The current event to process.
"""
if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
print()
#GPIO.output(25,True) see https://stackoverflow.com/questions/44219740/how-can-i-get-an-led-to-light-on-google-assistant-listening
if event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
print("got some work to do here with the phrase or text spoken!")
print(event)
if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED and
event.args and not event.args['with_follow_on_turn']):
print()
#GPIO.output(25,False) or also see https://blog.arevindh.com/2017/05/20/voice-activated-google-assistant-on-raspberry-pi-with-visual-feedback/
I'd like code to react to the ON_RECOGNIZING_SPEECH_FINISHED event I think and at either do my own action by matching simple requests or if the phrase is not in my list then let Google handle it. How do I do that?
Eventually I'd be asking "OK Google, turn BBC1 on" or "OK Google, play my playlist" or "OK Google, show traffic" and hotword.py would run other applications to do those tasks.
Thanks, Steve
See the documentation here for all available methods -
https://developers.google.com/assistant/sdk/reference/library/python/
You can use the stop_conversation() method to stop Google Assistant handling that request and act on your own.
Here's what you need to do at a high level -
Build your own dictionary of commands that you'd like to handle -
"turn BBC1 on", "play my playlist" etc.
On EventType.ON_RECOGNIZING_SPEECH_FINISHED event check if the
recognized command exists in your dictionary.
If the recognized command exists in your dictionary call the assistant.stop_conversation() method and handle the command on your own. If not do nothing (let google handle it)
pseudo code -
local_commands = ['turnBBCOn', 'playLocalPlaylist']
function turnBBCOn() :
#handle locally
function playLocalPlaylist() :
#handle locally
def process_event(event):
if event.type == EventType.ON_CONVERSATION_TURN_STARTED:
print()
if event.type == EventType.ON_RECOGNIZING_SPEECH_FINISHED:
print(event.args['text'])
if event.args['text'] in local_commands:
assistant.stop_conversation()
if(event.args['text']='turn BBC1 on')
turnBBCOn()
elif(event.args['text']='play my playlist')
playLocalPlaylist()
if (event.type == EventType.ON_CONVERSATION_TURN_FINISHED and
event.args and not event.args['with_follow_on_turn']):
print()
I have recently integrated google assistant SDK with Raspberry Pi 3. I have taken reference from below git repository and created action.py and actionbase.py classes can handle my custom command. I found it very clean and flexible way to create your own custom commands.
You can register your custom command in action.py file like below
actor = actionbase.Actor()
actor.add_keyword(
_('ip address'), SpeakShellCommandOutput(
say, "ip -4 route get 1 | head -1 | cut -d' ' -f8",
_('I do not have an ip address assigned to me.')))
return actor
action.py
Write your custom code in action.py
"""Speaks out the output of a shell command."""
def __init__(self, say, shell_command, failure_text):
self.say = say
self.shell_command = shell_command
self.failure_text = failure_text
def run(self, voice_command):
output = subprocess.check_output(self.shell_command, shell=True).strip()
if output:
self.say(output.decode('utf-8'))
elif self.failure_text:
self.say(self.failure_text)
You can full source code here. https://github.com/aycgit/google-assistant-hotword
The text is contained within the event arguments. By calling event.args you can make use of the text. Here is an example.
https://github.com/shivasiddharth/GassistPi/blob/master/src/main.py

Tkinter link button press and 'return' key

I've looked at various tutorials for how to link a button press and a keyboard press of 'return.' I can do them both, but only one at a time. The keyboard style is rootWindow.bind('<Return>' functionName and that linking an on-screen button is command=functionName. I just can't get them to work when used at the same time.
This is the very basic skeleton of what I'm working with
def printthis(event):
print("worked")
root = Tk()
root.bind('<Return>', printthis)
button1 = Button(root, text='Enter', command=printthis)
button1.pack()
root.mainloop()
I get this error when I run the current code, I'm just not sure what 'event' I should pass into the command=printthis section
TypeError: printthis() missing 1 required positional argument: 'event'
As a side note I am using Python 3.x
When you bind a function an event object will be passed into it whenever the binding action occurs. If you want your function to work for both on event and button press then you have two options.
First is if your function may require the event object. Then allow your function to take an optional argument for event.
def printthis(event = None):
if event is None:
# handle this case
# otherwise handle event object normally.
The second is if you don't care about the event object then the 1st is still fine (you just never use the event parameter), or you can use lambda when binding.
def printthis():
print("worked")
root.bind('<Return>', lambda e: printthis())
lambda takes e which is the event object and then calls your function without passing in e discarding it.

DalekJS and Mithril: Test are too fast

I use Dalek to test my sample to-do application written with help of Mithril framework.
Everything goes fine until .type() comes in.
If I .type() something in input that have bi-directional binding m.prop with m.withAttr and then assert values of that field i get strage behaviour. Instead "test title" I get "tsttle". It seems that test are running too quickly for Mithril to capture changes and render them back to DOM.
If assertions for input equality is removed — all works just fine.
Is there any workaround, can I slow down type process?
P.S. I use Chrome browser as test runner.
That definitely is an interesting issue, the problem is though, that Dalek can't control the speed of the letters typed. This is due to the fact that the JSON-Wire Protocol does not give us a way to handle that, see here
One thing you could do, even if it seems like overkill, is to add a long function chain with explicit waits, like this:
.type('#selector', 'H')
.wait(500)
.type('#selector', 'e')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'l')
.wait(500)
.type('#selector', 'o')
You also could go ahead & write a utility function that handles that for you
function myType (selector, keys, test, wait) {
var keysArr = keys.split('');
keysArr.forEach(function (key) {
test.type(selector, key).wait(wait);
});
return test;
}
And then use it in your test like this:
module.exports = {
'my test': function (test) {
test.open('http://foobar.com');
myType('#selector', 'Hello', test, 500);
test.done();
}
};
Mithril, as of when I'm writing this, does a re-render on onkey* events. An option to avoid this is coming.
You could use attr::config at present to handle the onkey* events as this will not cause a rerender. For example:
m('input', {config: addHandler});
function addHandler (el, isInitialized, context) {
if (!isinitialized) {
el.addEventListener('onkeyup', keyHandler, false);
}
}
function keyHandler (event) { /* do something with key press */ }
Its possible {config: addHandler, onchange: m.withAttr('value', mpropData)} will do what you want, but I don't know Dalek. If its doesn't, then you can consider updating mpropData inside keyHandler.
Mithril renders asynchronously in response to event handlers (basically so that related groups of events like keypress/input all get a chance to run before redrawing)
You could try a few things:
if you have access to your data model from your test, you could run your assertion against that model value (which is updated synchronously), as opposed to using the DOM value which only gets updated on the next animation frame
otherwise, you could force a synchronous redraw by explicitly calling m.render (yes, render, not redraw) before running the assertion, to ensure the view is actually in sync w/ the data model
alternatively, you could try waiting for one animation frame (or two) before running the assertion