Getting Started with the Google API for Reading Public Calendars

I have a few public calendars at work that we use to show events taking place in various departments. I am creating a digital sign for one of our buildings and I'd like to be able to grab the events for the current day and display them on the digital sign. I'm most familiar with ruby right now, so I'm writing a ruby script to do this.

The first thing is I need to install the ruby google-api-client.

$ gem install google-api-client

Since all of the calendar data that I want to grab is on public calendars, I can use an API key to get all this data. Instructions for generating an API key are here: https://support.google.com/cloud/answer/6158862. You also need the calendarid for the calendars you want to grab data from.

In order to see if I have things set up correctly, the following script will grab all the entries from the calendar specified by the calendarid.

require 'google/apis/calendar_v3'

Google::Apis.logger.level = Logger::DEBUG

calendar = Google::Apis::CalendarV3::CalendarService.new
calendar.key='YOUR_API_KEY'
puts calendar.list_events('GOOGLE_CALENDAR_ID')

$ ruby simple_test.rb
...all calendar events show...

With the key working correctly, how can I limit the results to just a single day? And only see the fields that I'm interested in? For us, these are the summary, description, start date_time and location.

require 'google/apis/calendar_v3'

calendar = Google::Apis::CalendarV3::CalendarService.new
calendar.key='YOUR_API_KEY'

events = calendar.list_events('GOOGLE_CALENDAR_ID',
	always_include_email: false,
	time_min: '2018-04-23T00:00:00-05:00',
 	time_max: '2018-04-23T23:59:59-05:00'
)

events.items.each do |item|
	puts item.summary
	puts item.description
	puts item.start.date_time
	puts item.location
	puts "====="
end

I hope to have this script do a bit more. So I've put it on my github page. The repository is here: https://github.com/maryheintz/google-calendar-api-ruby

Root Logins with Key Required

I love the fact that I still have so much to learn. I was thinking that I should set things up so that root can ssh in to a computer but only if they have keys set up. One very quick google search and I had my answer.

[[email protected] ~]# grep PermitRoot /etc/ssh/sshd_config
PermitRootLogin without-password

I had just assumed the settings for PermitRootLogin were yes or no. It's great that the programmers also had thought of this other use. People are so much smarter than me.

Splitting a PDF File

I had a pdf file that was too large to email, but I needed to email.  So I quickly broke it up into two smaller files.  I used this command:

$ gs -dNOPAUSE -dBATCH -dFirstPage=1 -dLastPage=34 -sDEVICE=pdfwrite -sOutputFile=physics1.pdf -f Physics\ Faculty.pdf 
$ gs -dNOPAUSE -dBATCH -dFirstPage=35 -dLastPage=68 -sDEVICE=pdfwrite -sOutputFile=physics2.pdf -f Physics\ Faculty.pdf 

My New MacBook Pro

As noted, with the new year, I'm starting to use my new MacBook Pro full-time. Last night, it took a few hours to copy everything from my old backup to this new laptop. Did it work perfectly, of course not. Plus, I don't like copying everything from my old laptop to my new one. There is a lot of stuff that I could throw away, but it takes time to go through it all. So I copied just my old home directory, but not the Applications directory. I know there's lots of stuff that won't run or that should be updated, so I installed all that stuff manually.

Anyway, here's the info about my new laptop.

So it's not a current laptop. I bought it off the clearance section because I wanted a laptop that still had usb connections. The idea of carrying a bunch of dongles to plug stuff into a usb-c connection fills me with dread. I'll still have to do that for my network connection, but I do have usb and can still use my old chargers with an adapter. That's good because I didn't want to have to buy an extra one so that I could have one at home and work. I also bought a new 1tb hard drive and installed that myself. I couldn't customize the laptop because I bought it in the clearance section, so it came with a 128mb drive, which is laughable. It also comes only with 8gb of ram and I can't upgrade that. That's sad because my old laptop had 16gb of ram and I wanted one with even more, but Apple has decided that we don't need that much ram.

In my mind, I'm hoping this laptop takes me through retirement. And if that's the case, this will perhaps be my last mac. I'm not liking the direction that their hardware is taking and if I don't have to support macs at work, I really won't need one. I'd be fine with a linux laptop.

Took me a while, but my point of this post is to note that I'm moving from a 15-inch laptop to a 13-inch laptop. Yes, this new laptop is much lighter than my old one. But the screen feels really small as well. One place where I really notice it is in my calendar. The cells are all much smaller so that I can't see all my events. This may change how I use it. Now, I put lots of notes and reminders in my calendar. But if I can only view two or three events, I may stop putting items there. I'm already noticing that I don't really pay attention to the line that says 2 more... or 3 more..., meaning if I don't see them in the monthly view, it's like they're not there.

Another spot where I've noticed the smaller screen is in watching nhl games. It's changed the arrangement of how things are laid out. I'll probably get used to it, but my immediate reaction of course is that I don't like it. Oh well, change is inevitable.

Learning More Windows 10 Stuff

My last post talked about using xcopy to copy a bunch of files from one server to another. I had been running this for a day, but a couple of times the command failed with the error "Insufficient Memory". Since my new server has four times as much memory and three or four times as much disk space, I didn't think that error was actually true. A quick google search shows that this message usually comes up when filenames are over 255 characters long, which was going to be a problem for me. Instead, robocopy (robust copy) should be used. The command I'm now trying is:

robocopy U:\ F:\data /MIR /Z /XA:H /W:10

/MIR = specifies that robocopy should mirror the source directory and the destination directory. Beware that this may delete files at the destination
/Z = ensures robocopy can resume the transfer of a large file in mid-file instead of restarting
/XA:H = makes robocopy ignore hidden files, which is usually system stuff that we don't care about
/W:10 = reduces the wait time between failures to 10 seconds instead of the 30 second default

There's also one very large directory with software that I've downloaded that I don't want to copy. I can always just redownload it, so no sense in taking up space on my backup drive. So the command that I'm finally using is:

PS C:\> robocopy f:\data j:\edgwin\data /MIR /Z /XA:H /W:10 /XD "F:\data\installed_software"

Windows 10 – More Stuff I Didn’t Know

I'm installing a new Windows 10 computer in our office to replace the old Windows XP one. All this computer is going to do is host our shared windows disk. Not a lot of people use this disk, but it's really good for sharing files or if a student is going to work at different computers in the lab.

I have about 1tb of data on the old XP computer that I want to copy to the new Windows 10 computer. And I'd like to keep permissions, ownership, etc. of all the files. I googled around and found that xcopy is the command that I want. Specifically, something like this:

xcopy s:\sw f:\sw /O /X /E /H /K

I started windows powershell and tried to run this as me, since my account is a domain administrator. That didn't work. I always got access denied errors. So I tried to start powershell as administrator. Here, I couldn't "see" the s: drive, which was a mapped drive. I even tried logging in as a local computer account and then manually mounting the s: drive. Powershell would not see the drive mounted that way.

The solution was to login with my local administrator account. Then start windows powershell as administrator. The in powershell, run net use s: \\XPcomputer\sw, where I'd be prompted for my login credentials on our samba/ldap domain. Then, I could run:

xcopy s:\* f:\sw /O /X /E /H /K

What I found interesting is that after I did the net use command, I couldn't see the S: drive if I went to "This PC" even though it was currently copying from the S: drive. The screenshot below shows this. I found this weird. This may also have been true in earlier versions of windows, but I had never come across this before.

Windows 10 in My Samba PDC

I had recently installed windows 10 on one of our computers at work. I was able to successfully add it to the domain, but then none of my users could login. The error message was:

We can't sign you in with this credential because your domain isn't available.  Make sure your device is 
connected to your organization's network and try again.  If you previously signed in on this device with 
another credential, you can sign in with that credential.

This error message contains pretty much no information about the problem. The domain is/was available, as I was able to join it. After some looking around, I found that the problem is I missed a setting in my smb.conf file on my samba server. I needed to add this line for windows 10 computers:

server max protocol = NT1

Restart samba and things worked fine.

Note, this page gives you all the required settings for samba domains. Since I have been using the same smb.conf file for years, I didn't have the line needed because it's a more recent addition.

Merge Three Files into One Using Command Line

I have three pdf files that I want to merge into a single file. But I don't want the three files to be on three separate pages. I want one big page with the three files all there.

First, get the sizes of my files:

$ identify PusherDisc32017.pdf 
PusherDisc32017.pdf PDF 1224x792 1224x792+0+0 16-bit sRGB 58413B 0.000u 0:00.000
$ identify PressBlockShort32017.pdf 
PressBlockShort32017.pdf PDF 1224x792 1224x792+0+0 16-bit sRGB 51523B 0.010u 0:00.000
$ identify LongPressBlock32117.pdf 
LongPressBlock32117.pdf PDF 1224x792 1224x792+0+0 16-bit sRGB 49860B 0.000u 0:00.000

So I want my final image to be 1224 x (3x792) or 1224 x 2376. Now make an empty image that size. I'm using a white background.

convert -size 1224x2376 canvas:white hold.png

Now, one at a time, merge the files together:

$ composite PusherDisc32017.pdf hold.png out1.png
$ composite PressBlockShort32017.pdf -gravity center out1.png  out2.png
$ composite  LongPressBlock32117.pdf -gravity south  out2.png  out3.png

Now my file out3.png has what I want.

Problems with mp4 files in Firefox

We had some students who took a video with their phone and wanted to post it on an html page. The html code we used was:


In Chrome, this worked fine. But in Firefox, it would show like this.

When that happened, I went to Tools -> Web Developer -> Browser Console. I got a message like this:

HTTP "Content-Type" of "video/3gpp" is not supported.  Load of media resource http://www.example.com/Robot.3gp failed.

This message was strange because I wasn't posting a file called Robot.3gp, but one called Robot.mp4. So on my server, I checked the file.

$ file Robot.mp4
Robot.mp4: ISO Media, MPEG v4 system, 3GPP 

So whatever created this file, actually made a 3gpp file and not a legit mp4. However, I found that you can convert a 3gpp file to mp4 using ffmpeg. I renamed my Robot.mp4 file to Robot.3gp and then converted it.

$ ffmpeg -i Robot.3gp -ab 64k -ar 44100 -strict -2 Robot.mp4
ffmpeg version 2.8.12 Copyright (c) 2000-2017 the FFmpeg developers
  built with gcc 4.8.5 (GCC) 20150623 (Red Hat 4.8.5-11)
  configuration: --prefix=/usr --bindir=/usr/bin --datadir=/usr/share/ffmpeg --incdir=/usr/include/ffmpeg --libdir=/usr/lib64 --mandir=/usr/share/man --arch=x86_64 --optflags='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic' --extra-ldflags='-Wl,-z,relro ' --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvo-amrwbenc --enable-version3 --enable-bzlib --disable-crystalhd --enable-gnutls --enable-ladspa --enable-libass --enable-libcdio --enable-libdc1394 --disable-indev=jack --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-openal --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libvorbis --enable-libv4l2 --enable-libx264 --enable-libx265 --enable-libxvid --enable-x11grab --enable-avfilter --enable-avresample --enable-postproc --enable-pthreads --disable-static --enable-shared --enable-gpl --disable-debug --disable-stripping --shlibdir=/usr/lib64 --enable-runtime-cpudetect
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 60.100 / 56. 60.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 40.101 /  5. 40.101
  libavresample   2.  1.  0 /  2.  1.  0
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'Robot.3gp':
  Metadata:
    major_brand     : 3gp5
    minor_version   : 0
    compatible_brands: 3gp5isom
    creation_time   : 2017-07-26 17:45:04
  Duration: 00:00:20.23, start: 0.000000, bitrate: 5135 kb/s
    Stream #0:0(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p(tv, bt470bg/bt470bg/smpte170m), 720x480, 5005 kb/s, 30 fps, 30 tbr, 90k tbn, 180k tbc (default)
    Metadata:
      rotate          : 90
      creation_time   : 2017-07-26 17:45:04
    Side data:
      displaymatrix: rotation of -90.00 degrees
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 123 kb/s (default)
    Metadata:
      creation_time   : 2017-07-26 17:45:04
[libx264 @ 0x1e6d1e0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[libx264 @ 0x1e6d1e0] profile High, level 3.0
[libx264 @ 0x1e6d1e0] 264 - core 148 r2699 a5e06b9 - H.264/MPEG-4 AVC codec - Copyleft 2003-2016 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'Robot.mp4':
  Metadata:
    major_brand     : 3gp5
    minor_version   : 0
    compatible_brands: 3gp5isom
    encoder         : Lavf56.40.101
    Stream #0:0(und): Video: h264 (libx264) ([33][0][0][0] / 0x0021), yuv420p, 480x720, q=-1--1, 30 fps, 15360 tbn, 30 tbc (default)
    Metadata:
      creation_time   : 2017-07-26 17:45:04
      encoder         : Lavc56.60.100 libx264
    Stream #0:1(und): Audio: aac ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 64 kb/s (default)
    Metadata:
      creation_time   : 2017-07-26 17:45:04
      encoder         : Lavc56.60.100 aac
Stream mapping:
  Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264))
  Stream #0:1 -> #0:1 (aac (native) -> aac (native))
Press [q] to stop, [?] for help
frame=  607 fps=178 q=-1.0 Lsize=    1593kB time=00:00:20.22 bitrate= 645.1kbits/s    
video:1408kB audio:162kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 1.439324%
[libx264 @ 0x1e6d1e0] frame I:4     Avg QP:19.34  size:  9992
[libx264 @ 0x1e6d1e0] frame P:171   Avg QP:22.56  size:  4317
[libx264 @ 0x1e6d1e0] frame B:432   Avg QP:24.06  size:  1534
[libx264 @ 0x1e6d1e0] consecutive B-frames:  3.3%  2.6%  8.4% 85.7%
[libx264 @ 0x1e6d1e0] mb I  I16..4: 28.5% 58.4% 13.1%
[libx264 @ 0x1e6d1e0] mb P  I16..4:  4.2%  9.2%  1.8%  P16..4: 37.9%  7.7%  5.0%  0.0%  0.0%    skip:34.2%
[libx264 @ 0x1e6d1e0] mb B  I16..4:  0.3%  0.5%  0.1%  B16..8: 42.5%  2.7%  0.4%  direct: 1.4%  skip:52.2%  L0:48.5% L1:48.6% BI: 2.9%
[libx264 @ 0x1e6d1e0] 8x8 transform intra:59.6% inter:80.2%
[libx264 @ 0x1e6d1e0] coded y,uvDC,uvAC intra: 32.2% 41.0% 4.4% inter: 7.5% 10.5% 0.3%
[libx264 @ 0x1e6d1e0] i16 v,h,dc,p: 33% 24% 26% 18%
[libx264 @ 0x1e6d1e0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 10% 16% 45%  3%  9%  3%  9%  2%  3%
[libx264 @ 0x1e6d1e0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 13% 14% 27%  3% 18%  4% 16%  2%  3%
[libx264 @ 0x1e6d1e0] i8c dc,h,v,p: 61% 18% 20%  1%
[libx264 @ 0x1e6d1e0] Weighted P-Frames: Y:2.3% UV:0.0%
[libx264 @ 0x1e6d1e0] ref P L0: 56.2% 10.7% 21.3% 11.6%  0.1%
[libx264 @ 0x1e6d1e0] ref B L0: 84.3% 11.6%  4.1%
[libx264 @ 0x1e6d1e0] ref B L1: 94.4%  5.6%
[libx264 @ 0x1e6d1e0] kb/s:569.65
$ ll Robot*
-rwxr--r-- 1 hep html 12988147 Jul 27 12:53 Robot.3gp
-rw-rw-r-- 1 hep html  1630980 Jul 27 13:43 Robot.mp4
$ file Robot.3gp
Robot.3gp: ISO Media, MPEG v4 system, 3GPP
file Robot.mp4
Robot.mp4: ISO Media, MPEG v4 system, version 1

Now the Robot.mp4 file plays in Firefox without a problem.

Keyboard not working with old program setup

At work, we use some very old programs. In one program (layout), it opens up the other program (specctra). The weird error was that the keyboard would not work in specctra if it was started from layout. If I started it by itself from the command line, it worked perfectly. I looked at the logs when it started and found a lot of warnings that looked like this:

Warning: translation table syntax error: Unknown keysym name:  osfActivate
Warning: ... found while parsing ':osfActivate:            ManagerParentActivate()'
Warning: String to TranslationTable conversion encountered errors
Warning: translation table syntax error: Unknown keysym name:  osfBeginLine
Warning: ... found while parsing ':osfBeginLine:           ManagerGadgetTraverseHome()'
Warning: String to TranslationTable conversion encountered errors

Searching for this message brought me to this page. And the directions there worked perfectly.

[~]# cd /usr/
[/usr]# mkdir -p X11R6/lib
[/usr]# cd X11R6/lib/
[lib]# ln -s /usr/share/X11 .

After I created that link, the keyboard worked fine however specctra was started.