Java Sound on a Raspberry Pi with OpenJDK

try(InputStream inputStream = new BufferedInputStream(getClass().getClassLoader().getResourceAsStream("beep.wav"));
    AudioInputStream audioIn = AudioSystem.getAudioInputStream(inputStream)) {
    AudioFormat format = audioIn.getFormat();
    DataLine.Info info = new DataLine.Info(Clip.class, format);
    Clip clip = (Clip) AudioSystem.getLine(info);
    clip.open(audioIn);
    clip.start();
    Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch (UnsupportedAudioFileException | IOException | LineUnavailableException | InterruptedException  e1) {
    log.error("Error playing sound.", e1);
}

 

javax.sound.sampled.LineUnavailableException
 at org.classpath.icedtea.pulseaudio.PulseAudioMixer.openImpl(PulseAudioMixer.java:714)
 at org.classpath.icedtea.pulseaudio.PulseAudioMixer.openLocal(PulseAudioMixer.java:588)
 at org.classpath.icedtea.pulseaudio.PulseAudioMixer.openLocal(PulseAudioMixer.java:584)
 at org.classpath.icedtea.pulseaudio.PulseAudioMixer.open(PulseAudioMixer.java:579)
 at org.classpath.icedtea.pulseaudio.PulseAudioDataLine.open(PulseAudioDataLine.java:94)
 at org.classpath.icedtea.pulseaudio.PulseAudioDataLine.open(PulseAudioDataLine.java:283)
 at org.classpath.icedtea.pulseaudio.PulseAudioClip.open(PulseAudioClip.java:402)
 at org.classpath.icedtea.pulseaudio.PulseAudioClip.open(PulseAudioClip.java:453)

 

I was pretty bummed when my sound stopped playing on my Raspberry Pi when I switched to OpenJDK 8 after originally using Oracle JDK 8.

Editing the sound.properties for the OpenJDK solved my problem.

sudo vim /etc/java-8-openjdk/sound.properties

 

Comment out the icedtea classpath configs:

#javax.sound.sampled.Clip=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.Port=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.SourceDataLine=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider
#javax.sound.sampled.TargetDataLine=org.classpath.icedtea.pulseaudio.PulseAudioMixerProvider

 

Remove the comments from the sun classpath configs:

javax.sound.sampled.Clip=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.Port=com.sun.media.sound.PortMixerProvider
javax.sound.sampled.SourceDataLine=com.sun.media.sound.DirectAudioDeviceProvider
javax.sound.sampled.TargetDataLine=com.sun.media.sound.DirectAudioDeviceProvider

 

Problem solved.

SaltStack – Open an reverse SSH tunnel to a Raspberry Pi minion from the salt-master in AWS

Executing salt modules and states on minions is the normal way to interact with a minion, but sometimes it is a lot faster to manage a remote machine with a terminal shell over ssh. If that machine is behind a NAT, then it gets more difficult to ssh to that box, but if you control the salt master then you can setup a reverse SSH tunnel to the minion. Here’s how I did it from an AWS Lightsail salt-master and a Raspberry Pi without touching the minion except to set it up as a salt minion to my master. At some point I will likely turn this into a salt state so it can executed faster.

// It'd be better security-wise if you used a separate pivot machine instead of the salt master
// Generate an ssh key pair for a user on your salt-master
 ssh-keygen

// Copy your ssh public key to the salt-master file root
 sudo mkdir /srv/salt/ssh_keys
 sudo cp /home/ubuntu/.ssh/id_rsa.pub /srv/salt/ssh_keys/ubuntu.id_rsa.pub

// Create a new, limited user on your salt-master
// Ideally you would lock this user down as much as possible, 
// but still allow it to ssh to the salt-master and open up a reverse ssh tunnel.
 sudo useradd -m sshtunnel -s /bin/bash

// Generate ssh keys for sshtunnel
 sudo ssh-keygen -f sshtunnel

// Copy the key to your salt file root
 sudo cp sshtunnel /srv/salt/ssh_keys/sshtunnel.id_rsa

// Add they public key in sshtunnel.pub to authorized_keys file
 sudo cp sshtunnel.pub /home/sshtunnel/.ssh/authorized_keys
 sudo chown -R sshtunnel:sshtunnel /home/sshtunnel/.ssh

// Add your salt-master user's public ssh key to the 
// minion's /home/pi/.ssh/authorized_keys
 sudo salt minion01 ssh.set_auth_key_from_file pi salt://ssh_keys/ubuntu.id_rsa.pub

// Place salt master fingerprint in /home/pi/.ssh/known_hosts
 sudo salt minion01 ssh.set_known_host pi salt-master.example.com

// Generate a md5 sum of /srv/salt/ssh_keys/sshtunnel.id_rsa because 
// you'll need it when placing the file on the minion in the next command
 sudo md5sum /srv/salt/ssh_keys/sshtunnel.id_rsa

// Place ssh key from the master's /home/sshtunnel/.ssh/id_rsa on 
// the minion at /home/pi/.ssh/id_rsa
 sudo salt minion01 file.manage_file /home/pi/.ssh/id_rsa '' '{}' salt://ssh_keys/sshtunnel.id_rsa '{hash_type: 'md5', 'hsum': ''}' pi pi '600' base ''

//////////   MAKE THE CONNECTION ////////////////
// Open SSH Tunnel from the minion to the master with a port forward
 sudo salt minion01 cmd.run runas=pi 'ssh -f -R 7000:localhost:22 sshtunnel@salt-master.example.com sleep 30' --async
// Connect from the master to the minion on the local port that was opened
 ssh pi@localhost -p 7000
////////////////////////////////////////////////

// You are now connected to the minion and can manage and debug things faster
// Once you quit the ssh session, the minion->master ssh session will close

// Cleanup to avoid giving minions access to the master
// Remove ssh key from /home/pi/.ssh/id_rsa
 sudo salt minion01 file.remove /home/pi/.ssh/id_rsa

Zenoss 3.2 Email Alerts

After finding a bunch of Zenos 4 documents on the ‘Trigger’ tab, I became frustrated that I couldn’t find how to send email alerts in Zenos 3.2.  The Zenoss Core UI is extremely confusing.

Alerts can be created per user and per group.  Go to Advanced->Users->click user->Alerting Rules

Here you can create filters for events and get emailed about them.

JVM proxy through a remote/reverse SSH tunnel

You may come across a scenario where you need to test your Java application from an alternate network, or you may not have sufficient network access where your code/application resides.  The JVM comes equipped with awesome proxy capabilities using SOCKs and a more specific HTTP proxy.  These can be set as environment properties when starting the JVM (http.proxyHost,http.proxyPort,socksProxyHost,socksProxyPort) or set programatically.  You can even configure a ProxySelector class for advanced proxy logic.  See Oracle’s Documentation for advanced usage.

Your http requests can go through SOCKs as well, but if the HTTPProxy is defined, then it will use the more specific proxy for the protocol it needs.

Here’s an example of the JVM options you would use to start your Java application to use proxies:

-Xmx2G -Dhttp.proxyHost=192.168.1.2 -Dhttp.proxyPort=80 -DsocksProxyHost=192.168.1.2 -DsocksProxyPort=1080

But, what if you don’t have direct access to the proxy server? You’ll need to use an SSH Tunnel. What if you can’t SSH out of your box? If you can SSH in, you can still create a remote/reverse tunnel. Here’s how that is done in Putty. Right click on the top of your active ssh putty window and chose ‘Change Settings’. Add the tunnels shown in the screenshots below to your connection. I noticed that sometimes ssh servers don’t have permissions to open up lower-numbered ports, so it took some trial and error before discovering that higher-numbered ports worked. The destination address of the tunnel is where the port will be forwarded to. The ‘Dynamic’ setting turns the tunnel into a SOCKs proxy itself and may be good if you don’t have a SOCKs server available, but I never got this working, but could have been because I was trying lower port numbers.

Putty1

Putty2

After you add those ports and apply the settings to your putty ssh session, your development machine now has two listening ports, one for http proxy, one for SOCKs proxy. Then you point your JVM at the localhost ports rather than the remote proxy ports.

-Xmx2G -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8555 -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8666

The SOCKs proxy in the JVM will even tell MySQL database connections to use the proxy. If you want a specific Apache HttpClient connection to use the proxy, you can configure it like this:

DefaultHttpClient client = new DefaultHttpClient();
HttpHost proxy = new HttpHost(“127.0.0.1”, 8555, “http”);
client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);

or

client.getParams().setParameter(“socksProxyHost”,”127.0.0.1″);
client.getParams().setParameter(“socksProxyPort”, 8666);

If you are using Java’s URL class to make a request you can set a proxy for it:

Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(“127.0.0.1”, 8555));
HttpURLConnection connection = (HttpURLConnection) new
URL(myUrlString).openConnection(proxy);

If you are developing on a Windows box and need to SSH into that box, a good SSH Server that allows you to open up tunnels is COPSSH.

 

Adding a gmail alias for a forwarded google domains address

I decided to give domains.google.com a try and I like the email forwarding feature and the free private whois listing. After forwarding an email like admin@yournewfancydomain.com to your @gmail.com address, it isn’t straight forward to get gmail to add your forwarded email address as an alias so you can send from that address. I searched their docs and couldn’t find how to do this. Here’s the steps that Google Support provided to me to do it.

 

In Google Accounts:

  1. Go to Google Accounts

  2. Login using the recipient email address.

  3. Click the Security tab.

  4. Look for App passwords under the Password section. Note: The App Passwords option will only be visible if you have 2-Step Verification enabled.

  5. Click Settings under App passwords.

  6. Under Select app choose Mail.

  7. Under Select Device choose your respective device.

  8. Click Generate.

  9. Take note of the generated app password and just click Done.

 

In Gmail:

  1. Click the gear at the top right corner.

  2. Select Settings.

  3. Click Accounts and Import.

  4. Click Add another email address you own under Send mail as.

  5. Enter your alias email address then click Next Step. Keep the Treat as alias checked.

  6. Enter these values:

    • SMTP Server: smtp.gmail.com
    • Port: 465
    • Username: Your Gmail email address.
    • Password: The generated app password from Step 9.

        7.  Click Add Account.

        8.  Click the verification link sent to your Gmail.

It will then be possible to send using an alias. You may do a quick test by composing an email and choosing your email alias in the From field.

 

 

Thrive Life Pro is leaving Beta

It’s been exciting to get Thrive Life Pro to the point that we can leave beta. We have been able to acquire a lot of users that are excited to use it and improve their ability to manage their time in their Thrive Life businesses. Thrive Life Pro (TLPro) is a contact management system that allows Thrive Life consultants to assign tasks and associate them with events and contacts. It helps keep consultants organized and helps them communicate more effectively with their customers, downline, and prospects.

100% height div not working

Sometimes, even with a lot of tricky css, you still can’t get a div to stretch to the height of it’s parent. Sometimes this height is also determined by an adjacent table cell. In this case, JavaScript and jQuery come in handy.

        jQuery('.innerWrapper').css('height', 'auto');
        var maxHeight = 0;
        jQuery('td.outerCell').each(function() {
            var height = jQuery(this).outerHeight();
            if (height > maxHeight) {
                maxHeight = height;
            }
        });
        jQuery('.innerWrapper').css('height', maxHeight);