My Photo Stream will be shut down on July 26

I’ve been getting emails announcing the end of My Photo Stream for some time now. I didn’t know what implications it might have since I’m not paying Apple for cloud storage, only using the tiny bit they give away for free.

In the past various friends have invited me to participate in shared albums in the Apple Photos ecosystem and I have been impressed at how smoothly it works. I assumed the storage quota counted against the friend that set up the album.

I was on a reunion trip recently and looked at the Apple support page for shared albums and realized that they don’t count against anyone’s quota so I set one up and invited a bunch of friends to contribute. For some of the friends accepting the access was easy, for others they never seemed to be able to get in.

Digging around in the iCloud settings caused me to find the setting that enabled My Photo Stream. I use OneDrive to back up the photos on my iPhone so duplicating the last 30 days of photos into iCloud didn’t seem very important to me, and is a security hole I didn’t realize I had.

The scary thing is that if I try to turn off the feature, the iPhone warns that it will delete photos from my iPhone. Are the photos currently duplicated into the Photo Stream album? I don’t mind deleting them from the cloud, but the iPhone is already enough of a black box, I don’t really know where everything is stored and don’t want to lose original quality photos. Until I learn more I don’t want to manually disable the feature.

C++ IPv6 Ping Code Example

My previous code example for IPv4 needed a bunch of modifications to work for an IPv6 address. The thing that took me the longest to figure out was that because IPv6 seems to send a lot more ICMP messages on the local network, I needed to filter the response messages to only the type I was listening for.

bool send_ping6(const std::string& ping_ip, const std::string& HostName4Output, const bool bOutput = false)
{
    bool rval = false;
    if (bOutput)
        std::cout << "[" << getTimeExcelLocal() << "] " << "send_ping6(" << ping_ip << ", " << HostName4Output << ");" << std::endl;
    struct timespec tfs;
    clock_gettime(CLOCK_MONOTONIC, &tfs);
    auto ping_sockfd = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
    if (ping_sockfd < 0)
    {
        if (bOutput)
            std::cout << "[" << getTimeExcelLocal() << "] " << "Socket file descriptor not received!!" << std::endl;
    }
    else
    {
        // set socket options at ip to TTL and value to 64,
        // change to what you want by setting ttl_val
        int ttl_val = 64;
        if (setsockopt(ping_sockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl_val, sizeof(ttl_val)) != 0)
        {
            if (bOutput)
                std::cerr << "[" << getTimeExcelLocal() << "] " << "Setting socket options to TTL failed!" << std::endl;
        }
        else
        {
            struct icmp6_filter filt;
            ICMP6_FILTER_SETBLOCKALL(&filt);
            ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
            setsockopt(ping_sockfd, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt));

            // setting timeout of recv setting
            struct timeval tv_out;
            tv_out.tv_sec = RECV_TIMEOUT;
            tv_out.tv_usec = 0;
            setsockopt(ping_sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv_out, sizeof(tv_out));

            int msg_count = 0;
            int flag = 1;
            int msg_received_count = 0;
            // send icmp packet in a loop
            for (auto pingloop = 4; pingloop > 0; pingloop--)
            {
                // flag is whether packet was sent or not
                flag = 1;

                //filling packet
                struct ping_pkt pckt;
                bzero(&pckt, sizeof(pckt));
                for (auto i = 0; i < sizeof(pckt.msg) - 1; i++)
                    pckt.msg[i] = i + '0';
                pckt.msg[sizeof(pckt.msg) - 1] = 0;
                pckt.hdr.type = ICMP6_ECHO_REQUEST;
                pckt.hdr.un.echo.id = getpid();
                pckt.hdr.un.echo.sequence = msg_count++;
                pckt.hdr.checksum = checksum(&pckt, sizeof(pckt));

                usleep(PING_SLEEP_RATE);

                struct timespec time_start;
                clock_gettime(CLOCK_MONOTONIC, &time_start);

                struct sockaddr_in6 ping_addr;
                ping_addr.sin6_family = AF_INET6;
                ping_addr.sin6_port = htons(0);
                inet_pton(AF_INET6, ping_ip.c_str(), &ping_addr.sin6_addr);
                if (sendto(ping_sockfd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&ping_addr, sizeof(ping_addr)) <= 0)
                {
                    if (bOutput)
                        std::cout << "[" << getTimeExcelLocal() << "] " << "Packet Sending Failed!" << std::endl;
                    flag = 0;
                }

                //receive packet
                struct sockaddr_in6 r_addr;
                auto addr_len = sizeof(r_addr);
                if (recvfrom(ping_sockfd, &pckt, sizeof(pckt), 0, (struct sockaddr*)&r_addr, (socklen_t*)&addr_len) <= 0 && msg_count > 1)
                {
                    if (bOutput)
                        std::cout << "[" << getTimeExcelLocal() << "] " << "Packet receive failed!" << std::endl;
                }
                else
                {
                    struct timespec time_end;
                    clock_gettime(CLOCK_MONOTONIC, &time_end);

                    double timeElapsed = ((double)(time_end.tv_nsec - time_start.tv_nsec)) / 1000000.0;
                    long double rtt_msec = (time_end.tv_sec - time_start.tv_sec) * 1000.0 + timeElapsed;

                    // if packet was not sent, don't receive
                    if (flag)
                    {
                        char szAddr[NI_MAXHOST] = { 0 };
                        inet_ntop(AF_INET6, &r_addr.sin6_addr, szAddr, sizeof(szAddr));
                        if (!(pckt.hdr.type == ICMP6_ECHO_REPLY && pckt.hdr.code == 0))
                        {
                            if (bOutput)
                                std::cout << "[" << getTimeExcelLocal() << "] " << "Error..Packet received from (" << szAddr << ") with ICMP type " << int(pckt.hdr.type) << " code " << int(pckt.hdr.code) << std::endl;
                        }
                        else
                        {
                            if (bOutput)
                                std::cout << "[" << getTimeExcelLocal() << "] " << PING_PKT_S << " bytes from (" << szAddr << ") (" << HostName4Output << ") msg_seq=" << msg_count << " ttl=" << "ttl_val" << " rtt= " << rtt_msec << " ms." << std::endl;
                            msg_received_count++;
                        }
                    }
                }
            }
            rval = msg_received_count > 0;
            struct timespec tfe;
            clock_gettime(CLOCK_MONOTONIC, &tfe);
            double timeElapsed = ((double)(tfe.tv_nsec - tfs.tv_nsec)) / 1000000.0;
            long double total_msec = (tfe.tv_sec - tfs.tv_sec) * 1000.0 + timeElapsed;
            if (bOutput)
                std::cout << "[" << getTimeExcelLocal() << "] " << "=== " << ping_ip << " ping statistics === " << msg_count << " packets sent, " << msg_received_count << " packets received, " << ((msg_count - msg_received_count) / msg_count) * 100.0 << " percent packet loss. Total time : " << total_msec << " ms." << std::endl;
        }
        close(ping_sockfd);
    }
    return(rval);
}

Because my calling routine is keeping the addresses for the hosts as strings, I’m calling each of these routines with those strings and converting them to proper addresses inside the function. I’m making a simple choice of whether it’s an IPv4 address or an IPv6 address by the fact that IPv4 addresses have “.” in them and IPv6 addresses have “:”.

bool send_ping(const std::string& ping_ip, const std::string& HostName4Output, const bool bOutput = false)
{
    bool rval = false;
    if (ping_ip.find('.') == std::string::npos)
        rval = send_ping6(ping_ip, HostName4Output, bOutput);
    else 
        rval = send_ping4(ping_ip, HostName4Output, bOutput);
    return(rval);
}

Here’s a bunch of links I found useful while creating this code:

USPS Informed Delivery Daily Digest and Netflix DVDs

I use the USPS service Informed Delivery and highly recommend it. I get a daily email from USPS with a scanned picture of most of the mail that will arrive in my mailbox that day. Occasionally the email will say that there were items that could not be scanned, but it’s very useful since I don’t check my mailbox on a daily basis, but don’t want to have important items sit for extended times.

My mailbox is fairly secure, but I’ve also read that Informed Delivery has both good and bad features for people related to mail theft or identity theft.

I’ve been getting Netflix DVDs in the mail since 2000.  I’ve always been slightly fascinated with the efficiencies the post office and Netflix have worked out. If I take a DVD mailer to my local post office here in Seattle, Netflix recognizes it has been returned the next business day. If I drop a DVD at the local post office on Tuesday, Netflix acknowledges it on Wednesday, and I’ve usually got the next DVD delivered Thursday.

Until recently the Netflix DVDs were scanned like all other mail.

2019-09-13 (3)

It appears to have changed at the beginning of September. Now there’s a pair of fixed images arriving with a link that will take you directly to Netflix.

2019-09-13 (2)

The new behavior isn’t bad since all the Netflix disk scans look very similar, but are interesting to note. I wouldn’t be surprised that the new full color image reduces bandwidth over individual scans along with added benefit of the link to Netflix.

Using FFMPEG to Convert Video a GIF

My brother in law and niece were on the stock footage the local news used for football fans tonight. I already have built a program that allows transferring shows from my TiVo to my PC. I just needed a few manual commands in FFMPEG to get a useful bit to share.

After transferring the entire tv show to my PC I watched it in VLC Media Player to find the minute and second I wanted to start with, and the minute and second I wanted to finish with. I came up with starting at 24 minutes 24 seconds, and finishing at 24 minutes 36 seconds.

The command I used to capture 12 seconds was:

ffmpeg -i "KBOI 2 News at 5_30pm (Recorded Dec 27, 2016, KBOIDT).mp4" -vcodec copy -acodec copy -ss 00:24:24.000 -t 00:00:12.000 CactusBowlPromo.mp4

Then I further trimmed the section into an animated GIF with just the portion I was really interested in:

ffmpeg -i CactusBowlPromo.mp4 -ss 00:00:07.350 -t 00:00:02.200 CactusBowlPromoJoeMegan.gif

I did some trial and error on both the start time and the length, but I got what I wanted with the tools I had sitting around.

Megan and Joe at BSU Football

FrSKY Taranis RC Transmitter

Following several friends recommendations I purchased a FR Sky Taranis radio to control my quad copter. I wanted more channels of communication than what my original transmitter supplied, as well as the ability to choose which switches controlled which activities on my UAV. The Taranis was fairly inexpensive for its feature set, but has been in limited supply. I had myself put on a waiting list from http://www.alofthobbies.com/ to be notified when they had them in stock. I received mine about a month ago, and while I took pictures and have used it in the past month, this is the first time I’ve sat down and consolidated that information. I purchased the Taranis & X8R combination that includes both the transmitter and receiver. It included the protective carrying case, rechargeable battery, AC adapter, neck strap and balancing clip, as well as the transmitter and receiver. A small zip-lock bag contained keys for the carrying case and two pin jumpers for configuring the receiver outputs. There is a green LED visible between the battery compartment and the charger port that blinks when the battery is being charged and goes solid when it is completely charged. I wish that the LED was visible on the front because everything else is on the front, and I don’t really want to lay the device in its front during the charging period but would like to know when it’s done charging.

Taranis Travel Case

Taranis Travel Case

Taranis Contents

Taranis and accessories

Taranis Battery Compartment
Taranis Charging

The X8R receiver has 8 standard PWM channel outputs as well as a Futaba compatible SBus output. The standard outputs can be configured as either outputting channels 1-8 or channels 9-16. The X8R is capable of receiving 16 channels and sending controls for those 16 channels over the single SPort connection. I am connecting it to my Pixhawk using the single SBus connection. Arducopter running on my Pixhawk currently only pays attention to the first 8 channels. I may configure the standard outputs on my X8R to output channels 9-16, and connect my camera gymbal controls directly to the X8r, allowing me to utilize all the channels currently.

The Pixhawk is designed with a single input control set of pins, using PPM instead of PWM. PWM stands for Pulse Width Modulation. PPM stands for Pulse Position Modulation. Pulse Position Modulation allows for packing multiple channels into a single signal. There are plenty of good examples describing the technology as it related to RC devices, if you know the right terms to search for. I started learning RC airplanes last summer, and understanding what was going on didn’t seem as easy as it should be. The APM board that I was originally using had 8 PWM inputs, and 8 PWM outputs. The inputs were connected to the receiver and the outputs were connected to the ESCs, Electronic Speed Controls, for the motors. Now I’m using the Pixhawk and it’s got a single three wire cable connecting to the receiver but still 4 three wire cables connecting to the 4 ESCs. http://www.endurance-rc.com/ppmtut.php is one description of PPM vs PWM.

The Taranis itself runs OpenTX operating system which accounts for a large portion of its flexibility compared to its cost. It reports data back from the receiver as well, so technically both the transmitter and receiver are transceivers, sending data as well as receiving data. A simple bit of data that it constantly reported back at the transmitter is RSSI, the receiver signal strength. This is useful simply to recognize before you fly your model out of range of your transmitter. This return data path should also be able to carry all of the telemetry back and display it directly on the transmitter. I’ve not figured out if the pixhawk needs to be connected to two ports on the x8r to accomplish this feature.

What follows is a link dump of many of the items I’ve been saving up in understanding my configuration of the taranis radio, using the 16 channels, using the pixhawk, my Tarot GoPro gymbal, and references to the APM as well.

 

eSATA and PCI Power Management

My home server that I built using an HP ProLiant N40L Microserver was recently running low on disk space. It has four internal bays for 3.5 inch drives, and I had fully populated those. It has a single eSATA port but that eSATA port does not support drive enclosures with multiple targets.

TowerRAID TR4M+BNCI decided I would buy a Sans Digital 4 Bay eSATA Port Multiplier JBOD Tower Storage Enclosure (no eSATA Card bundle) TR4M+BNC and populate it with four Western Digital Red NAS Hard Drive WD30EFRX 3TB IntelliPower 64MB Cache SATA 6.0Gb/s 3.5″ Internal Hard Drives. I could have used 4TB drives, but the 3TB drives were at a better price per byte point for me. I was mainly interested in storage space, and not so much speed.

SI-PEX40060Because the built in eSATA port on my machine would not support multiple targets without hacking the bios, I decided the easy thing was to buy an eSATA card to put in my machine. I picked SYBA SI-PEX40060 PCI-Express 2.0 x1 Low Profile Ready SATA III (6.0Gb/s) Controller Card because it explicitly listed Port Multiplier compatibility and I’ve used devices from SYBA in the past.

I had to install the driver for the card to get it to recognize more than the first drive in the enclosure but then I was able to use the normal windows disk management utility to configure each of the four drives. The front panel of the Sans Digital box went from having a single green hard drive led to having all four lit up. I got the drivers for the card from the manufacturer web page instead of using the CD that shipped with the card. http://www.sybausa.com/productInfo.php?iid=1383

I configured all four new drives into a software raid configuration and started to put data onto the system. It was seeming slow, but I let it run overnight. When I next looked at it, the drive letters assigned to the drives on the array were offline, and the array display only had a single LED lit.

Some research and I found these messages in the event log:

Log Name:      System
Source:        mv91xx
Date:          4/1/2014 6:55:39 AM
Event ID:      117
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      Acid.WIMSWORLD.local
Description:
The driver for device \Device\Scsi\mv91xx1 detected a port timeout due to prolonged inactivity. All associated busses were reset in an effort to clear the condition.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="mv91xx" />
    <EventID Qualifiers="49156">117</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2014-04-01T13:55:39.043910900Z" />
    <EventRecordID>220446</EventRecordID>
    <Channel>System</Channel>
    <Computer>Acid.WIMSWORLD.local</Computer>
    <Security />
  </System>
  <EventData>
    <Data>\Device\Scsi\mv91xx1</Data>
    <Binary>000000000100000000000000750004C0000100000000000000000000000000000000000000000000</Binary>
  </EventData>
</Event>

Log Name:      System
Source:        mv91xx
Date:          4/1/2014 6:55:41 AM
Event ID:      9
Task Category: None
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      Acid.WIMSWORLD.local
Description:
The device, \Device\Scsi\mv91xx1, did not respond within the timeout period.
Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="mv91xx" />
    <EventID Qualifiers="49156">9</EventID>
    <Level>2</Level>
    <Task>0</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2014-04-01T13:55:41.062170100Z" />
    <EventRecordID>220447</EventRecordID>
    <Channel>System</Channel>
    <Computer>Acid.WIMSWORLD.local</Computer>
    <Security />
  </System>
  <EventData>
    <Data>\Device\Scsi\mv91xx1</Data>
    <Binary>0F0010000100000000000000090004C001010050000000002D05000000000000000000000000000000000000000000000000000007000000</Binary>
  </EventData>
</Event>

Searching on the error code led me to a web page describing a similar issue with a different driver. http://solutions.unixsherpa.com/2010/03/25/the-device-deviceideiastor0-did-not-respond-within-the-timeout-period/ refers to PCI-Express Link State Power Management as the instigator to my problem. I changed the power management exactly like the page said and my machine has been completely stable for the last month.

Tool Lending Libraries

I learned about tool lending libraries while I was visiting the Seattle Mini Maker Faire last month. I’ve not had time since to take advantage of any of them but I was just finding some of this information interesting.

 

Vertical Surface Pen Plotter

A month ago I want to the Seattle Mini Maker Faire at the EMP Museum. (March 22/23 2014) and saw several items that interested me.

http://www.marginallyclever.com/shop/drawing-robots/makelangelo-3-complete-kit was one such item. It uses two motors at the top corners of a drawing space to suspend a pen holding device that raises and lowers a marker from the surface.

The most interesting thing mentioned to me was that the top corners could use suction cups and draw an image on a window. ROBO-0019_1