Sunday, September 5, 2021

Elenco Capacitor Substitution Kit

 

-----

Not often (okay, almost never) a capacitance substitution box would come in handy on the bench.   Finally, the Amazon AI wizard suggested that at $14.99 we couldn't live life any longer without one. 

From the pic above you can see that the included wire and alligator clip connector were replaced with banana plug jacks.   It gives the rig and the bench a cleaner look.

-----

The directions (which we folded up and placed inside the box for future generations) were straight forward and the values are accurate enough per a NIST traceable capacitance meter.   

-----

The same company also makes a resistance substitution box which we also don't need, but will probably build up anyway.  Both are a nice, cheap, welcome convenience. 

-----

Sunday, May 30, 2021

Remote CW Straight Key [FlexRadio and RemoteHams.Com]

Note:  As presented this project requires a FCC Amateur Radio license.  It's not hard to get and it is a fun and rewarding hobby. Also, learning Morse code is no longer a requirement.

-----

As a remote ham radio operator that enjoys using a manual CW (Morse code) straight key we were presented with two problems:

Since both require slightly different hardware wiring to the PC running the remote rig, we set out to make something that would be a universal connection regardless of which platform we are using. 

-----

The hardware connection is simple and shown below.  It does require a USB/RS-232 adapter and using the RS-232 terminal block break out module shown makes things easier.   There are many example of these two items on Amazon.Com, etc.

For both applications software is needed as well.

-----

For our RemoteHams.Com solution go here.

-----

For the FlexRadio solution you will need to install the excellent and easy to use Remote Keyer Interface software.   Follow the RKI link for the software and you will also find the very helpful RKI message board that I personally proved is helpful and tolerant of 'stupid' questions.  Seriously, the software has great documentation and even though I asked a "RTFM" question I got helpful direction from the forum.   After you install and run the RKI software you will see this screen: 

Make the remote connection to your FlexRadio via your SmartLink login and select the correct COM Port for your (now) USB straight key.  Verify the other options are selected per above screen shot and you should be good to go.

BTW, Remote Keyer Interface software has several other cool features in addition to this simple application.

-----

Summary:   My remote CW manual straight keying problems are solved!

-----

Wednesday, May 26, 2021

The Tale of Three USB Chargers

 

-----

Everyone seems to have a box full of USB chargers.   Well, we do anyway and decided to pick two random "no name" chargers and pit them up against an official Apple USB charger.

The test setup was the same for each USB charger.   We swept a load that increases from 100mA until the USB charger went into protection (no voltage output).  We then checked EMI/RF Noise and 'vampire drain'.

EMI/RF Noise is a big concern.  EMI/RF can have a negative effect on WiFi, Bluetooth, ham radio, and pretty much any radio signal in the area.  Measuring with a Spectrum Analyzer the Apple was by far the most RF quite.  The White "no name" was extremely EMI/RF noisy with the Black "no name" being pretty bad as well.

"Vampire drain" or standby power is how much energy the charger uses when just plugged into the wall doing nothing.  The Apple won in this category as well.

My opinion, get the Apple or other well made USB charger and avoid the "no names",  The Apple uses less standby power and should not have a negative effect on your or your neighbors wireless equipment.  The Apple power output meets spec as well and is more linear until protection kicks in.  The Apple is just better and some "no names" are are just unsafe.

-----

-----

-----

-----

Thursday, May 20, 2021

Morse Code QSO via Vintage Phone

 

-----

As a preteen many many years ago the thought never occurred that the same phone used to plan childhood mischief would some day be used for a CW (Morse code) ham radio QSO.   Ain't life funny...

-----

We found the old Western Electric phone in the attic and wired the switch hook as a straight key.

 


 -----

Then we went to 80m where we heard ham radio operator K5JM and decided to "ring" him up.  The result; success!!!

-----

73!



Friday, May 14, 2021

NanoVNA on QPRGuys Tuner on 10-80m HWEF


 -----

Adjusting the tuning knobs on the QRPGuys tuner and showing their effect with a NanoVNA.   Antenna is 10-80m endfed

-----

Tuesday, May 11, 2021

2m / 70cm Ham Radio Traffic Logger

http://2.bp.blogspot.com/-JEWIVBP404I/YJrWhjILDgI/AAAAAAAAxKk/4vh5lUMph7cgCha-dcdaXxRp3YSFXEInQCK4BGAYYCw/s1600/BT_Logger_Schmatic-793823.JPG 

Is the frequency in use (or QRL? in Morse Code)?

-----

We had a curiosity about how often some of the local ham radio repeaters and the 2m calling frequency was being used and decided to put together a rig that could answer the question with real data.    Ham radio has a lot to do with experimentation and tinkering so we set out on a mission to answer the question with "stuff" we had laying around the shack.

-----

Pretty much any newcomer to ham radio has invested $35'ish on a Baofeng hand held.  The little unit is quickly out grown, but it has come in useful time and time again.   This project was just another example of it's unintended usefulness.  Also, like most hobbyist there's never a shortage of WiFi friendly ESP8266s laying around.   Combining the two for an RF activity logger became the objective.

-----

And..... it turned out to be pretty easy and didn't even require opening up the Baofeng.   Anytime the Baofeng hears a signal the LCD display light is activated.   For reasons unknown this presents a voltage spike on the speaker jack.   We suspected this could be the case from the loud "pop" that can be heard when using earphones.

-----

Here is a look at the signal generated on the speaker jack when the display light gets activated:

Weird, huh?   Oh well, we can use that to make the project dead simple.  Just tune the Baofeng to the frequency of interest and let the rig run and log any traffic that hit the antenna.

-----

The schematic at the top of the page shows how we feed the speaker signal into the analog input (A0) of the ESP8266.   To tame the 5 volt signal going into the ESP8266 two diodes are placed back to back.   That's it.   The ESP8266 is programmed to update a Google Drive Sheet via an IFTTT Webhook anytime a voltage is detected.   The activity log looks like this and the source code is below that.  If you duplicate the project, let us know.

-----

-----

/*
 *  Baofeng Traffic Logger
 *  MAY2021
 *  WhiskeyTangoHotel.Com
 *   
 *  Logs to Google Sheet is traffic is dectected on BF HT Radio    !!!  
 *  by monitoring a voltage on the speaker output.  On traffic the !!!
 *  BF display lights and creates a voltage on the speaker jack    !!!
 *  Since no transit, does not require a license, but if you don't !!!
 *  have a ham license, get one.  It's a fun hobby!!!              !!!  
 *  See: http://www.arrl.org/getting-licensed                      !!!
 *  
 *  uC setting for Ardunio IDE (ESP8266 with WiFI)
 *  NodeMCU 1.0 (ESP-12E Module), 80MHz, 921600, 4M (3M SPIFFS)
 *  
*/

// For the Wireless
#include <ESP8266WiFi.h>

// WiFi Connection Information
const char* ssid = "yourSSID";           // PRIVATE: Enter your personal setup information.
const char* password = "yourpassword";   // PRIVATE: Enter your personal setup information.

// IFTTT Information for WebHook widget
String MAKER_SECRET_KEY = "yourIFTTTkey";   // PRIVATE: Enter your personal setup information. Your IFTTT Webhook key here
String TRIGGER_NAME_google_drive = "yourIFTTTWebHookTriggerName";  // this is the Maker IFTTT trigger name for google drive spreadsheet logging
String url_google_drive;  // url that gets built for the IFTTT Webhook logging to google drive spreadsheet
String Status ="Program_Started.....";  // Status payload for Google Sheet.  We log all starts and reboots
const char* host = "maker.ifttt.com";

// Define ESP8266 pins
const int led = 2;  // Blue on board LED is on PIN-D4 (GPIO2) for this NoderMCU 1.0 ESP8266.  Blink it between reads
const int analogInPin = A0;  // ESP8266 Analog Pin ADC0 = A0

int sigValue = 0;  // value to determine if a signal is detected

// Program control variables
int logging = 1; // If 1 then send SMS.  Any other value (0) turns it off.  For debug, typically would be set = 1

void setup(void){ // This setup code is run once.
  pinMode(led, OUTPUT);     // set up the onboard Blue LED pin as an output.  
  Serial.begin(115200);     // turn on the serial monitor for debug

  // wait until serial port opens for native USB devices
  while (! Serial) {
    delay(10);
  }
 
  // Is the WiFi working?
  WiFi.begin(ssid, password);
  Serial.println("");
  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print("Trying to connect to ");
    Serial.print(ssid);
    Serial.print(" on ");
    Serial.print(WiFi.localIP());
    Serial.println(" ");
    for (int x = 0; x < 20; x++) { //  
      digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED. Shows program is trying to WiFi connect
      //Serial.println("Server Start blink loop....");
      delay(50);   
    } // endfor WiFi blink connect
  }
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.println(WiFi.localIP());

  for (int x = 0; x < 10; x++) { // 5 slow LED blinks to slow WIFI Connected.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
  Serial.println("WIFI is Connected....");
  delay(500);   } // endif for WIFI Connected blink  

  // Use WiFiClient class to create TCP connections for WiFi logging
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");  // Boo!!!
    return;
  }

  // Trigger the IFTTT Webhook Channel to update a Google sheet at program start.
  // This can help log power outs, etc.  For first run we defined String Status for identify a startup condition.
  // Create the request for IFTTT google drive
  url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
  Serial.println(" ");  
  Serial.println("Status: Google Sheet update done with trigger:");
  Serial.println (url_google_drive);
  Serial.println(" ");  
    
  // This sends the request to the IFTTT server
  client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
  "Host: " + host + "\r\n" +
  "Connection: close\r\n\r\n");  
  delay(500);  // Delay for web traffic; maybe not required.  

  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
     String line = client.readStringUntil('\r');    }

}


void loop(void){    // Loop until the Dallas Cowboys win a Super Bowl
 
  sigValue = analogRead(analogInPin);
 
  // For Degug print SigVal readings in the Serial Monitor
  //Serial.println(sigValue);

  // The blue onboard LED will SLOW blink between to show prog is 'running'.
  // FAST blink when sig is dectected.
  digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED.
    
  if (sigValue > 500) {  //  Threshold may need adjusting.  Voltage on speaker jack detected.  We have a signal
      Serial.println("!!!_Signal_Detected_!!!");   
      Serial.println(" ");
              
      if (logging == 1) { // is Google Sheet logging turned on?
          Serial.println("***** Logging is ON *****");
          String Status = "!!!_Signal_Detected_!!!";
          // Set up IFTTT Webhook Channel to update the Google Sheet.  
          // Use WiFiClient class to create TCP connections for IFTTT
          WiFiClient client;
          const int httpPort = 80;
          if (!client.connect(host, httpPort)) {
            Serial.println("connection failed");
            return;
          }
          
          // Create the request for IFTTT google drive
          url_google_drive = "https://maker.ifttt.com/trigger/" + TRIGGER_NAME_google_drive + "/with/key/" + MAKER_SECRET_KEY + "?value1=" + String(Status);
            
          // This sends the request to the IFTTT server
          client.print(String("POST ") + url_google_drive + " HTTP/1.1\r\n" +
          "Host: " + host + "\r\n" +
          "Connection: close\r\n\r\n");  
          delay(500);  // Delay for web traffic; maybe not required.  
        
          // Read all the lines of the reply from server and print them to Serial
          while(client.available()){
             String line = client.readStringUntil('\r');    }
                  
          Serial.println("Status: Google Sheet update done with trigger:");
          Serial.println(url_google_drive);
          Serial.println(" ");
          
          // Fast blink the blue onboard LED to show sig was dectected and delay for flood control
          for (int x = 0; x < 600; x++) { // x = 20 for ~ 1 sec, x = 100 for ~5 sec.....
              digitalWrite(led, !digitalRead(led));  // toggle state of the on board blue LED
              delay(50);   
          } // endfor delay/blink
          
          Serial.println("-------------------------------------");
          Serial.println("Waiting for signal... ");
           
      } else {
        
          Serial.println("Logging is OFF.");
          Serial.println(" ");
      } // endif/else logging  


            
  }
  delay(250); // Delay for onboard blue LED Blink shows program running
    
} // void loop until Cowboys win Super Bowl

-----

Wednesday, January 20, 2021

Flex Radio Turned Boat Anchor

Have you ever wanted the nostalgic sound of a vintage ham radio rig only to be stuck with an expensive modern transceiver?

-----

Note:  As presented this project requires a FCC Amateur Radio license.  Amateur Radio is about experimentation.   Even still you must be versed in the band plan, stay in accordance to FCC Amateur Radio rules in FCC Section 97, and probably a few other things.  That said, let's continue....
-----

The Flex Radio 6400 is an amazing state of the art ham radio transceiver with so many modern bells and whistles than no normal human could ever get around to using them all.   But, sometimes you long to send out that relaxing and warm sound that could only be achieved from a vintage "boat anchor" radio.  A signature trademark of these rigs is their inability to hold steady on a frequency.  This results in frequency drift.  This 'feature' is lost in modern rigs like the Flex Radio.  So what's a modern ham to do when that vintage sound is desired?

-----

The Flex Radio is a SDR; think powerful computer turned radio.   Flex allows third party applications to interface with the radio to make it even more powerful.   One such program is FRStack .  One of FRStack's many many features makes it easy to use API calls to control and configure the Flex Radio.  We wrote a simple Python script to have the Flex Radio simulate a drifting vintage ham radio during transmit.   We really don't recommend using this application; it's just stupid.  Our goal was to experiment with the APIs when the idea hit us. 

-----

 Here is a demo of the Flex Radio transmitting CW with the DriftyFlex script:

-----

Here is the short DriftyFlex Python script:

# DriftyFlex.py  JAN2021
# Python script to make the Flex Radio drift
# like that vintage rig you always wanted.
#
# WhiskeyTangoHotel.Com

# Simple novelty example of controlling
# a Flex Radio via FRStack

# FRStack is an amazing program with 100s of features that
# are a million times more useful than this stupid example.
# See: https://www.mkcmsoftware.com/Flex/Index

import urllib.request
import time
import random

# Define initial XIT offset XIT (0 is suggested)
XIT = 0

# Define amount of XIT SHIFT (or drift) per loop
SHIFT = 5  # in Hz

# Define MAX_XIT (or drift) so things don't get too out of control
MAX_XIT = 300  # in Hz

# Define how often to simulate a new drift
DELAY = .1   # in seconds

# turn on XIT mode
urllib.request.urlopen('http://localhost:13522/api/ActiveSlice/XIT?param=1')

print ( 'Drifty Flex endlesssssss loop.' )
while True:    
    DRIFT = (random.randint(-SHIFT, SHIFT))   

    NEW_XIT = XIT + DRIFT

    if abs(NEW_XIT) > MAX_XIT:  # Maintain drift constraints
        NEW_XIT = XIT - DRIFT
       
    url = 'http://localhost:13522/api/ActiveSlice/XITFREQ?param=' + str(NEW_XIT)
    urllib.request.urlopen( url )

    print ( 'Current drift is: ', NEW_XIT, ' Hz.' )
    XIT = NEW_XIT
    
    time.sleep(DELAY)
    # end while loop  

-----


Saturday, November 28, 2020

Ham Radio Fox Hunt Attenuator [FAIL]

 

-----

One of the many aspects of the ham radio hobby is finding a hidden transmitter; also called a fox hunt.  These are often set up by local clubs as a fun social activity, but they can also be competitive athletic events.  We had done a few fox hunts for fun, but were unsuccessful in finding the transmitter.  What we learned is when you get close to a transmitter (regardless of the power it is outputting) the signal becomes so strong there is no way to reliably get the direction information needed to track it down.   It's basically like a bright light blinding you and sunglasses are needed to reduce the input getting into your eyes.  To reduce the radio frequency (RF) signals picked up by your receiver (from the fox) an attenuator is used. 

-----

We saw this HMC472 Digital RF Attenuator Module on sale for $10US and thought it would be a cheap and simple project to solve our fox hunt problems.  We were wrong.....

It's not the module's fault; it works as spec'd.  Here are our measurement results from the bench:

-----
Wow, ten bucks buys a lot!   So....   what's the issue?  Well, after 3D printing a box for the rig we took it out into the field for a test drive and learned that 32dB attenuation is not nearly enough.   You need at least 100dB from what we later discovered.   Still, the final product came out nice, it did work as advertised, and things were learned.  We're gonna call that a win.  We could cascade a few modules to get more attenuation, but there are better solutions.  Here are some details on the simple build:
 
-----

Thursday, November 12, 2020

XR2206 Function Signal Generator DIY Kit

   

-----

We have seen this signal generator come up as "suggested" in our Amazon account from time to time.  Finally, the Amazon marketing engine combined with COVID cabin fever persuaded us to shell out the $10US and give the kit a try.  

----

$10 gets you a lot and not so much both at the same time.   First off, the directions are not very well written, but the kit is simply enough that they don't need to be.  We did have to ohm out the PCB just to verify that the NEG terminal for the electrolytic caps went into the "hashed" marked hole.   After about 20 minutes the kit was ready test out.  The results.....

-----

We took measurements with an oscilloscope for each setting.   Instead of putting up a bunch of boring sin, triangle, and square wave pics we will just state that the rig works as expected.   ONE CAVEAT:  THIS ONLY SEEMS TO BE TRUE WHEN YOU POWER THE RIG WITH 9VDC.  Also, adjusting the "Amp" knob can really effect the quality of the output signal.  There is a sweet spot on the "Amp" setting, but without a scope I'm not sure how you could find it.   Another odd behavior; a square wave will produce an almost 9V output.  The sin and triangle waves max out at about half that. 

-----

Here are our findings:

-----

So..... if you need a low end sig gen this kit does work.  It's cheap to buy.  It's easy and fun to build up.  But, be aware that without a scope you will not have a way to know the exact output frequency and output voltage or if the output signal is being clipped or otherwise deformed.  

-----

Sunday, August 30, 2020

Using Tesla Screen to Display FlexRadio SmartSDR

 

-----

We posted the video above of the FlexRadio 6400 streaming it's SmartSDR output to a Tesla on our Twitter feed and had several ham radio operators ask; "How did you do that"?  Well, it's a lot easier than you may think.

-----

Most hams never throw anything away and will find the materials needed to pull this off laying around their ham shack:

    - Tesla Model X

    - FlexRadio 6400

    - PC running FlexRadio's SmartSDR software

    - an internet connection

-----

After you have gathered the materials, it's easy.  Just go to the Dead Simple Screen Sharing site on the PC, click the button for the share link, then type that link into the browser on the Tesla.   The Dead Simple Screen Sharing site really is 'dead simple'.  I wouldn't suggest it for on-line banking, but for less critical applications it fits the bill.

Here is a slightly longer version of the demo:


-----

Thanks for watching and 73!



Wednesday, July 29, 2020

3D Printed FlexRadio Maestro Stand

-----
The stand for the FlexRadio Maestro is bulky and doesn't travel well.   FlexRadio does make folding feet to take care of this, but that solution is a hundred bucks.  We didn't need a less bulky travel stand all the time and we didn't want to part with the cash.  So.... we printed one.
-----
Works great!  Design file on Thingiverse.

-----

Sunday, July 19, 2020

3D Printed Single Lever Paddle/Cootie Morse Code Key


-----
We had originally printed this Morse Code key to operate in "Cootie" mode.  You can read about that here.   It turns out using a Cootie key is fun and easy on the wrist, but.....  learning to operate a Cootie key does take some practice.   That said, the automotive spark plug feeler gauge gave such an effortless feel we decided to make a small modification and create a Single Lever Paddle from the original design.
-----
This mod allows usage with an electronic keyer in three terminal mode.  The two terminals on the left can be shorted to quickly switch into Cootie mode.

Hardware parts list:

-----



-----

Tuesday, July 14, 2020

Send Morse Code (CW) with your Voice

-----
CW or Morse Code is a way ham radio operators send messages with a simple tone of two durations.  It was a must before the days of wireless voice communications and still remains popular because it is a fun challenge. 

There are many online tools that will convert text into Morse Code.  However, a Google AIY Voice Bonnet came into our possession and we thought we could take that another step by creating a "Speech to Morse" translator that would actually send code over the air on the ham radio bands from spoken word.

To use the rig, you don't need a ham radio license unless you connect to an actually ham radio transmitter; which is kinda the whole point.  My quick ham radio advertisement:  Get a FCC Amateur Radio license; it's not hard and is an extremely interesting hobby.  BTW, learning Morse Code is no longer a requirement.
-----
When we were given the AIY Voice Bonnet we really didn't even know what it did.  We knew it needed a Raspberry PI and it could act somewhat like a Google Voice Assistant.   We had a Raspberry PI Zero handy and after some Google search engineering we found a disk image file to get us started.

Like a lot of internet projects APIs can change and documentation can be conflicting, we finally got the RasPI and Voice Bonnet to talk to the web after some effort.  A full blown Google Voice Assistant this thing is NOT; if you want one of those then BUY, don't BUILD.  After leaning into the AIY GitHub for knowledge we were finally rewarded with success.
-----
The connections are easy and just follow the AIY GitHub to wire the ACTIVATE BUTTON. We used IO Pin 16 on the RasPI for the relay control because it wasn't used by the AIY Voice Bonnet.  The AIY Voice Bonnet has four GPIO pins on board, but we could never get them to work.   Here's the summary:
-----
And here is the rig in action.  The Python code to make it run is below.

Demo at 20 WPM:
Demo at 12 WPM:
-----
Thanks and 73!   Here is our Python source code:

#!/usr/bin/env python3

#
#  July  2020
#  Voice to Morse Code Translator
#  WhiskeyTangoHotel.Com
#
# RaspberryPI Zero and AIY Voice Bonnet.
#
# Use Google Voice AIY to convert speech to text.
# Read that text file created and convert the text.
# Turn that text into to Morse Code "." and "-".
# Close a relay to transmit it over the air with a ham radio
#
#
# BTW, CW is fun to learn.
# *  --... / ...--   //  --... / ...--

# Some program set up and Define some variables

import os  # needed to delete the text file after reading
import time  # needed for delays
from datetime import datetime # need to calc run time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM) # Use BCM I/O board pin numbers

SendingLine = 0  # this is the text file line we will send
StartCW = 0    #  Char position to start sending from the parsed line
EndCW = 0       #  Char position to stop sending from the parsed line

keyer = 16  # Pin where the keyer relay is connected
GPIO.setup(keyer, GPIO.OUT)
GPIO.output(keyer, GPIO.LOW)  # make certain we are not keyed down

# Load the CW database 'dits' and 'dahs' for each Alphanumeric. Boring....
A = ".-"
B = "-..."
C = "-.-."
D = "-.."
E = "."
F = "..-."
G = "--."
H = "...."
I = ".."
J = ".---"
K = "-.-"
L = ".-.."
M = "--"
N = "-."
O = "---"
P = ".--."
Q = "--.-"
R = ".-."
S = "..."
T = "-"
U = "..-"
V = "...-"
W = ".--"
X = "-..-"
Y = "-.--"
Z = "--.."
period = ".-.-.-"
zero = "-----"
one = ".----"
two = "..---"
three = "...--"
four = "....-"
five = "....."
six = "-...."
seven = "--..."
eight = "---.."
nine = "----."

# WPM spacing calculated using the "Paris Standard"
# Per Morse code convention: 1 Dah = 3 Dits, LETTERS are spaced by one Dit, WORDS are spaced by one Dah.

WPM = 20.0    # Don't leave off the ".0" or WPM will be an integer (we want it to float)
Dit = 1.200 / WPM
Dah = Dit * 3.0
between_ditdah_spacing = Dit
between_character_spacing = Dit * 2
between_word_spacing = Dit * 3

"""Calls to Google Assistant GRPC recognizer."""

# We use AIY in the cloud to do the speech to text processing.  The RaspberryPI just can't do it as good.

# Copyright 2017 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import locale
import logging
import signal
import sys

from aiy.assistant.grpc import AssistantServiceClientWithLed
from aiy.board import Board

def volume(string):
    value = int(string)
    if value < 0 or value > 100:
        raise argparse.ArgumentTypeError('Volume must be in [0...100] range.')
    return value

def locale_language():
    language, _ = locale.getdefaultlocale()
    return language

def main():
    logging.basicConfig(level=logging.DEBUG)
    signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(0))

    parser = argparse.ArgumentParser(description='Assistant service example.')
    parser.add_argument('--language', default=locale_language())
    parser.add_argument('--volume', type=volume, default=100)
    args = parser.parse_args()

    with Board() as board:
        assistant = AssistantServiceClientWithLed(board=board,
                                                  volume_percentage=args.volume,
                                                  language_code=args.language)
        while True:
            logging.info('Press button to start conversation...')
            board.button.wait_for_press()
            logging.info('Conversation started!')
            assistant.conversation()

            # Voice to CW routine starts here are the dim RED button is pressed
            # Button will turn bright RED while the rig is listening
            # Button will dim blink RED when ready for next speech input

            #  Read the text file created by the speech to text and get it ready to send as CW

            # Look for "Trigger Lines" in the text file.  Parse and send the line above it
            Trig1 = "Recording stopped."
            Trig2 = "End of audio request detected"
            Trig3 = "Updating conversation state"
            i = -1

            Get_file = "keywhat.txt"  # this is the text file created from AIY that we are going to process

            mylines = []
            with open (Get_file, 'rt') as myfile:    #'rt' means 'read text data'
                for line in myfile:
                    i = i + 1
                    mylines.append(line)
                   
                    # If we find one to the Trigger lines, we have passed the voice text by one line in the file
                    if mylines[i].find(Trig1) and mylines[i].find(Trig2) and mylines[i].find(Trig3)!= -1 :
                        SendingLine = i-1

            print (SendingLine, mylines[SendingLine])
            Send_text = mylines[SendingLine]

            #  Strip out only the text we want to send over the air
            StartCW = int((mylines[SendingLine].find('"')) + 1)
            EndCW = int(len(mylines[SendingLine]) - 3)
            # print StartCW, EndCW    #  used for debug

            SendasCW = Send_text[StartCW:EndCW]  # this is the text sent as CW

            #SendasCW = "test"  # used for debug
            SendasCW = (SendasCW.upper())  # and we always make certain it is all caps

            # We have the text.  Now parse it and send each letter as CW

            print ("Going to send: " + SendasCW + " at " + str(int(WPM)) + " WPM.")
            print ("-------------------------------------------")

            L = len(SendasCW)
            t0 = datetime.now()

            for x in range(0,L):  # Start character converstion to dit and dahs
                    Text_substring = SendasCW[x:x+1]
                    print ("Sending: " + Text_substring)   # for debug
                    if Text_substring == "0"  :  Text_substring = zero
                    if Text_substring == "1"  :  Text_substring = one
                    if Text_substring == "2"  :  Text_substring = two
                    if Text_substring == "3"  :  Text_substring = three
                    if Text_substring == "4"  :  Text_substring = four
                    if Text_substring == "5"  :  Text_substring = five
                    if Text_substring == "6"  :  Text_substring = six
                    if Text_substring == "7"  :  Text_substring = seven
                    if Text_substring == "8"  :  Text_substring = eight
                    if Text_substring == "9"  :  Text_substring = nine
                    if Text_substring == "."  :  Text_substring = period
                    if Text_substring == "A"  :  Text_substring = A
                    if Text_substring == "B"  :  Text_substring = B
                    if Text_substring == "C"  :  Text_substring = C
                    if Text_substring == "D"  :  Text_substring = D
                    if Text_substring == "E"  :  Text_substring = E
                    if Text_substring == "F"  :  Text_substring = F
                    if Text_substring == "G"  :  Text_substring = G
                    if Text_substring == "H"  :  Text_substring = H
                    if Text_substring == "I"  :  Text_substring = I
                    if Text_substring == "J"  :  Text_substring = J
                    if Text_substring == "K"  :  Text_substring = K
                    if Text_substring == "L"  :  Text_substring = L
                    if Text_substring == "M"  :  Text_substring = M
                    if Text_substring == "N"  :  Text_substring = N
                    if Text_substring == "O"  :  Text_substring = O
                    if Text_substring == "P"  :  Text_substring = P
                    if Text_substring == "Q"  :  Text_substring = Q
                    if Text_substring == "R"  :  Text_substring = R
                    if Text_substring == "S"  :  Text_substring = S
                    if Text_substring == "T"  :  Text_substring = T
                    if Text_substring == "U"  :  Text_substring = U
                    if Text_substring == "V"  :  Text_substring = V
                    if Text_substring == "W"  :  Text_substring = W
                    if Text_substring == "X"  :  Text_substring = X
                    if Text_substring == "Y"  :  Text_substring = Y
                    if Text_substring == "Z"  :  Text_substring = Z

                    #  Now send the dit/dahs for the Self Test Callsign Character
                    CW_length = int(len(Text_substring))

                    time.sleep(between_character_spacing) # a delay between characters

                    for j in range(0, CW_length):     # Send tones and blink LED in CW

                            Dit_or_Dah = Text_substring[j:j+1]

                            # HIGH closes a relay connect to the ham radio.  LOW opens the relay
                            # This relay closure is the same as pushing down on a straight key

                            if (Dit_or_Dah) == "."  :    # process a Dit
                                    print (Dit_or_Dah)
                                    GPIO.output(keyer, GPIO.HIGH)
                                    time.sleep(Dit) # a delay of "1 Dit" between dit/dahs in a character
                                    GPIO.output(keyer, GPIO.LOW)  #make certain we are not keyed down
                                    time.sleep(between_ditdah_spacing) # a delay bewteen characters
                                    # end if process a Dit

                            if (Dit_or_Dah) == "-"  :    # process a Dah
                                    print (Dit_or_Dah)
                                    GPIO.output(keyer, GPIO.HIGH)
                                    time.sleep(Dah) # a delay of "1 Dit" between dit/dahs in a character
                                    GPIO.output(keyer, GPIO.LOW)  #make certain we are not keyed down
                                    time.sleep(between_ditdah_spacing) # a delay bewteen characters
                                    # end if process a Dah

                            if (Dit_or_Dah) == " "  :    # process a SPACE (delay between words)
                                    print ("<SPACE>")
                                    GPIO.output(keyer, GPIO.LOW)  #make double certain we are not keyed down
                                    time.sleep(between_word_spacing) # a delay of "3 Dit" between words
                                    # end if process a SPACE


            GPIO.output(keyer, GPIO.LOW)  #make absolutely certain we are not keyed down

            t1 = datetime.now() - t0  # how long did it take to send?

            print ("-------------------------------------------")
            print ("Completed in " + str(t1) + " seconds at " + str(int(WPM)) + " WPM to send:")
            print (SendasCW)

            # close and delete voice to text cloud file to get ready for the next voice decode
            time.sleep(1)  # file handling delay, probably not needed
            myfile.close()
            os.remove(Get_file)
            time.sleep(1)  # file handling delay, probably not needed
            myfile = open(Get_file, "w")

if __name__ == '__main__':
    main()
-----