Check if button is pressed or not - ruby

I have a Raspberry Pi with a Siri Proxy that is controlling my garage door, the garage door has only one command for open and close. To check if the garage door is opened to not I bought a magnet switch and I builded a flout point button. I already tried
doorstate = `gpio read 5`.chomp #gives value 1 or 0, 1 is opened, 0 is closed
print doorstate
if doorstate == "1"
print "The garage door is already opened.\n"
elsif doorstate == "0"
print "OK, I'll open it for you!\n"
else
print "Error, please open it manually.\n"
end
Can someone please tell me how I can check fi the returned value or string from doorstate = 'gpio read 5' is equal to a string?

I'm guessing here that the result of 'gpio read 5' contains a line ending.
Try chomping it off:
doorstate = `gpio read 5`.chomp
To verify the class of doorstate, insert p doorstate.class at line 2.

You need to change your single quotes (') to backticks (`, the little thing with the tilde on your keyboard). That will execute the command. The rest of your code is fine.

Related

Ruby is there a way to stop the user from calling a function/procedure through case before they have accessed a different function/procedure?

I have a text file that I want to open first for reading or writing, but want the user to manually enter the text_file name (which opens the file for reading) first like so:
def read_in_albums
puts "Enter file name: "
begin
file_name = gets().chomp
if (file_name == "albums.txt")
puts "File is open"
a_file = File.new("#{file_name}", "r")
puts a_file.gets
finished = true
else
puts "Please re-enter file name: "
end
end until finished
end
From this unfinished code below, selecting 1 would go to the above procedure. I want the user to select 1 first, and if they choose 2 without having gone through read_in_albums they just get some sort of message like "no file selected and sent back to menu screen.
def main()
finished = false
begin
puts("Main Menu:")
puts("1- Read in Album")
puts("2- Display Album Info")
puts("3- Play Album")
puts("4- Update Album")
puts("5- Exit")
choice = read_integer_in_range("Please enter your choice:", 1, 5)
case choice
when 1
read_in_albums
when 2
display_album_info
when 5
finished = true
end
end until finished
end
main()
The only thing I can think of is something like
when 2
if(read_in_albums == true)
display_album_info
and have it return true from read_in_albums.
which I don't want to do as it just goes through read_in_albums again, when I only want it to do that if the user pressed 1.
All of your application's functionality depends on whether the album data has been read. You are no doubt storing this data as an object in memory referenced by some variable.
$album_data = File.read 'album.txt'
You can test whether this data is present in order to determine whether the file data has been read:
if $album_data.nil?
# ask user for album file
else
# show album user interface
end
There is no need for a separate flag. The mere presence of the data in memory serves as a flag already.
You could either set a flag when option 1 was selcted
has_been_read = false
...
when 1
read_in_albums
has_been_read = true
when 2
if has_been_read
display_album_info
else
puts "Select Option 1 first"
end
Or just test if your file name is a valid string.

Currently trying to script a game and I don't understand how to debug this section of coding

I'm following a youtube tutorial on scripting to create a game on roblox and whilst following it, "Status", the variable I use to identify a value decides to stop working (line39). My output box says the following:
21:16:36.197 - sword game.rbxl auto-recovery file was created
21:16:36.715 - ServerScriptService.MainScript:39: Expected ']' (to close '[' at line 37), got 'Status'
21:16:38.617 - ScriptNavigationHandler : No script currently available.
I haven't learned much about debugging code but if someone can shine some light on what is wrong that would greatly help me on my conquest to learn scripting during the fight against the invisible enemy.
-- Define varibles
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local MapsFolder = ServerStorage:WaitForChild("Maps")
local Status = ReplicatedStorage:WaitForChild("Status")
local GameLength = 60
--Game loop
while true do
Status.Value = "Waiting for enoughplayers"
repeat wait(1) until game.Players.NumPlayers >=2
Status.Value = "Intermission"
wait(8)
local plrs = {}
for i, player in pairs(game.Players:GetPlayers()) do
if player then
table.insert(plrs,player) --Add each player into plrs table
end
end
wait(2)
local AvaliableMaps =MapsFolder:GetChildren()
local ChosenMap = AvaliableMaps[math.random(1,#AvailableMaps)
Status.Value = ChosenMap.Name "Chosen"
local ClonedMap = ChosenMap:Clone()
ClonedMap.Parent = workspace
-- Teleport players to the map
local SpawnPoints = ClonedMap:FindFirstChild("SpawnPoints")
if not SpawnPoints then
print("SpawnPoints not found!")
end
local AvailableSpawnPoints = SpawnPoints:GetChildren()
for i, player in pairs(plrs) do
if player then
character = player.Character
if character then
-- Teleport them
character:FindFirstChild("HumanoidRootPart").CFrame = AvailableSpawnPoints[1].CFrame
table.remove(AvailableSpawnPoints,1)
-- Give Sword
local Sword = ServerStorage.Sword:Clone()
Sword.Parent = player.Backpack
local GameTag = Instance.new("BoolValue")
GameTag.Name = "GameTag"
GameTag.Parent = player.Character
else
-- There is no character
if not player then
table.remove(plrs,i)
end
end
end
end
end
In
local ChosenMap = AvaliableMaps[math.random(1,#AvailableMaps)
you are missing the closing square bracket.
Night94 has pointed out the correct fix for your broken code, but since your question is about learning to debug, I'll try to help you understand your error messages.
21:16:36.715 - ServerScriptService.MainScript:39: Expected ']' (to close '[' at line 37), got 'Status'
Let's break this down piece by piece :
ServerScriptStorage.MainScript:39 this tells us where the file is, and on what line the error appeared.
So let's look at line 39 (through 41) you see :
local ChosenMap = AvaliableMaps[math.random(1,#AvailableMaps)
Status.Value = ChosenMap.Name "Chosen"
Next we have : Expected ']' (to close '[' at line 37), got 'Status'
This means that at some point, the code was expecting a square bracket to close the one that was opened at 37 : AvaliableMaps[, but instead it found the next line of code Status
So with these pieces of information, you should have all the pieces to understand what went wrong: A square bracket was opened, but never closed. It should go somewhere before the next line of code.
local ChosenMap = AvaliableMaps[math.random(1,#AvailableMaps)]

Making a flashing console message with ruby

0.upto(9) do
STDOUT.print "Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b\b" # (6 backspaces, the length of "Flash!")
sleep 0.5
end
This code doesn't work. It prints Flash! to the screen, but it doesn't flash. It just stays there, as though the backspaces aren't taking effect. But I do this:
0.upto(9) do
STDOUT.print "Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b" # (5 backspaces, the length of "Flash! - 1")
sleep 0.5
end
and it almost works. It prints this: FFFFFFFFFFlash!(after 9 loops) Why do the backspaces stop taking effect when their number is equal to the length of the string they're deleting?
How can I overcome this problem and create a flashing message, only using libraries that are part of rails?
I tried a workaround like this:
0.upto(9) do
STDOUT.print " Flash!"
sleep 0.5
STDOUT.print "\b\b\b\b\b\b"
sleep 0.5
end
(Note the space in " Flash!"), but what happens is the message appears to crawl across the screen! An interesting effect, but not what I want.
I'm using Command Prompt with Ruby and Rails in Windows 7
Typically this would be written something like:
0.upto(9) do
STDOUT.print "\rFlash!"
sleep 0.5
STDOUT.print "\r " # Send return and six spaces
sleep 0.5
end
Back in the days when we'd talk to TTY and dot-matrix printers, we'd rapidly become used to the carriage-control characters, like "\r", "\n", "\t", etc. Today, people rarely do that to start, because they want to use the web, and browsers; Learning to talk to devices comes a lot later.
"\r" means return the carriage to its home position, which, on a type-writer moved the roller all the way to the right so we could start typing on the left margin again. Printers with moving heads reversed that and would move the print-head all the way to the left, but, in either case, printing started on the left-margin again. With the console/telnet/video-TTY, it moves the cursor to the left margin. It's all the same, just different technology.
A little more usable routine would be:
msg = 'Flash!'
10.times do
print "\r#{ msg }"
sleep 0.5
print "\r#{ ' ' * msg.size }" # Send return and however many spaces are needed.
sleep 0.5
end
Change msg to what you want, and the code will automatically use the right number of spaces to overwrite the characters.
Anyway, it looks like backspace (at least in windows) just positions the cursor back, you need/want to overwrite the character with a space at that point (or 6 of them) to "blank" the text out.
Or, you can just use this
def text_flasher(text)
puts "\e[5m#{text}\e[0m"
end
use text_flasher in the console and you'll see the magic :)
Right, based on #rogerdpack 's input I have devised a solution:
def flashing_output(output)
message = output
backspace = "\b"
space = " "
backspace_array = []
space_array = []
length = message.length
length.times do
backspace_array << backspace
space_array << space
end
0.upto(9) do
print message
sleep 0.5
print backspace_array.join.to_s + space_array.join.to_s + backspace_array.join.to_s + backspace_array.join.to_s
sleep 0.5
end
end
flashing_output("Flashing Foobars! (not a euphemism)")

Cucumber and variables internal to methods called indirectly

Please note: I am new to TDD & cucumber, so the answer may be very easy.
I am creating a basic image editor for a test (the image is just a sequence of letters).
I have written a Cucumber story:
Scenario Outline: edit commands
Given I start the editor
And a 3 x 3 image is created
When I type the command <command>
Then the image should look like <image>
The step
Scenarios: colour single pixel
| command | image |
| L 1 2 C | OOOCOOOOO |
always fails, returning
expected: "OOOCOOOOO"
got: " OOOOOOOO" (using ==) (RSpec::Expectations::ExpectationNotMetError)
This is the step code:
When /^I type the command (.*)$/ do |command|
#editor.exec_cmd(command).should be
end
The function exec_cmd in the program recognizes the command and launches the appropriate action. In this case it will launch the following
def colorize_pixel(x, y, color)
if !#image.nil?
x = x.to_i
y = y.to_i
pos = (y - 1) * #image[:columns] + x
#image[:content].insert(pos, color).slice!(pos - 1)
else
#messenger.puts "There's no image. Create one first!"
end
end
However, this always fails unless I hardcode the values of the two local variables (pos and color) in the function in the program itself.
Why? It doesn's seem I'm doing anything wrong in the program itself: the function does what it's supposed to do and those two variables are only useful locally. So I'd think this is a problem with my use of cucumber. How do I properly test this?
---edit---
def exec_cmd(cmd = nil)
if !cmd.nil?
case cmd.split.first
when "I" then create_image(cmd[1], cmd[2])
when "S" then show_image
when "C" then clear_table
when "L" then colorize_pixel(cmd[1], cmd[2], cmd[3])
else
#messenger.puts "Incorrect command. " + "Commands available: I C L V H F S X."
end
else
#messenger.puts "Please enter a command."
end
end
When /^I type the command (.*)$/ do |command|
#output = #editor.exec_cmd(command)
end
Then /^the image should look like (.)*$/ do |expected_image|
#output.should == expected_image
end
Hope this may help you.
It's not a cucumber issue.
The problem was that, in exec_cmd, split was called only in the "case" clause, not in the "when"s. This meant that, since the command's format was "a 1 2 b", cmd[1] in the "when" would call the second character of the string, a space, not the second value of the array, and the other functions would convert that to_i, returning 0.
I changed exec_cmd like this:
def exec_cmd(cmd = nil)
if !cmd.nil?
cmd = cmd.split
case cmd.first
when "I" then create_image(cmd[1], cmd[2])
[...]
end
which fixed the issue.

I want AutoIt to activate a particular tab in Firefox. How can this be done?

I have several tabs open in Firefox. I want AutoIt to activate a particular tab in Firefox. How can this be done?
Give the whole browser window focus, then use the send command to repeatedly send it cntl-tab until the window's title is the name of the tab you want (with - Mozilla Firefox at the end).
There's a UDF (User Defined Functions -include file) called FF.au3. Looks like the function you want is _FFTabSetSelected(), good luck!
Below is an example of Jeanne Pindar's method. This is the way I would do it.
#include <array.au3>
Opt("WinTitleMatchMode", 2)
activateTab("Gmail")
Func activateTab($targetWindowKeyphrase)
WinActivate("- Mozilla Firefox")
For $i = 0 To 100
If StringInStr(WinGetTitle(WinActive("")),$targetWindowKeyphrase) Then
MsgBox(0,"Found It", "The tab with the key phrase " & $targetWindowKeyphrase & " is now active.")
Return
EndIf
Send("^{TAB}")
Sleep(200)
Next
EndFunc
Here you go...
AutoItSetOption("WinTitleMatchMode", 2)
$searchString = "amazon"
WinActivate("Mozilla Firefox")
For $i = 0 To 100
Send("^" & $i)
Sleep(250)
If Not(StringInStr(WinGetTitle("[ACTIVE]"), $searchString) = 0) Then
MsgBox(0, "Done", "Found it!")
ExitLoop
EndIf
Next
Just delete the MsgBox and you're all set!
As Copas said, use FF.au3. Function _FFTabSetSelected($regex,"label") will select first tab with name matching given $regex.
Nop... The script is buggy ^^'... no need to count to 100, and there is a problem with the "send" after it:
If you send ctrl + number
=>the number can't be bigger than 9... Because ten is a number with 2 caracters, Firefox can't activate tab 10 with shortcut.
And by the way when the script is working there is a moment he release the ctrl key.. It don't send ten, but ctrl and 1 end zero ... and splash !!! It just send the number in the window.
So we need to learn to the script that the second time he's back to $i = 0 or one, all the tabs was seen, no need to continue, even if the text you're searching for was not found.
So I made my own script based on the old one:
##
AutoItSetOption("WinTitleMatchMode", 2)
$searchString = "The string you're looking for"
Local $o = 0
WinActivate("The Name of the process where you're searching")
For $i = 0 To 9
Send("^" & $i)
Sleep(250)
if ($i = 9) Then
$o += 1
EndIf
If not (StringInStr(WinGetTitle("[ACTIVE]"), $searchString) = 0) Then
MsgBox("","","Found it !") ;your action, the text was found.
ExitLoop
ElseIf ($o = 1) Then
MsgBox("","","All tab seen, not found...") ;your action, the text was not found, even after looking all title.
ExitLoop
EndIf
Next
##
I haven't touched AutoIt in years, but IIRC it will be:
setMousePos(x, y) // tab position
click("left")

Resources