Software Archive

I have been running a build of Cyanogen mod that I initially discovered at http://galaxytabhacks.com/galaxy-tab-10-1-roms/cm10-jelly-bean-rom-for-galaxy-tab-10-1-android-4-1-2/ when I initially received the tablet from my wife back ATC Christmas (and had upgraded from Honeycomb within just a few hours).  Since I’ve got the next week off from work and I had really wanted to get a little better performance out of Google Now, I decided to finally give one of the nightlife a try this evening. I did my Nandroid backup and performed the update, then updated gapps t the latest version from goo.im. Still working some kinks out, and indeterminate at this point whether I will remain on this version (Google Now does appear to b working great) or restore the Nandroid. 

My major complaint with the nightly is that the keyboard crashes every couple of seconds; that’s a Royal pain in the ass, as its surprising just how much text entry I do on my tablet. After more pissing around than I really like, I did finally locate a replacement keyboard that is fairly similar to the AOSP version (which I find comfortable for typing and pretty accurate at replacing words with what I intended to type) and that doesn’t crash. In case you find yourself in the same boat, check out Jelly Bean Keyboard. It’s not identical, but thus far I have found it comfortable. I’ll give it a couple of days and see how it grows on me.

In hindsight I probably would have just stuck with the 10/30 build from the post I originally linked, and I may yet revert. It was ridiculously stable and the battery life was absolutely unbelievable. Also still unable to update to the most current version of Google Search from the Play Store – crashes every time I attempt to launch it after installing the update until I roll back to the default version. Still, I will give it a couple of days before I firmly make up my mind.

Be the first to comment

http://blogs.computerworld.com/android/21359/make-hottest-android-home-screens-yourself

Need to share this one, I’m sure I know a few people who would find some of these customizations very enjoyable.

Be the first to comment

http://www.computerworld.com/s/article/9234897/10_free_Drupal_modules_that_make_development_easier

Need to take a read through this, might have a couple of places where it could help make things easier.

Be the first to comment

Android Phone as an IP Camera

Posted January 19, 2013 By Landis V

My wife mentioned a listing on one of the Facebook exchange groups that have become popular lately, and it got me thinking about a topic I’ve considered before, but in a new way.

A similar model of Levana monitor from Amazon.

The listing was for a Levana Era baby monitor (similar to the one pictured at left), which does appear to be well received and fairly feature rich, and which we will probably end up purchasing as well, because my projects always tend to exist in a state of perpetual beta! As I was reading about the features and functionality of the Levana product, I had the same thought I always have when looking at cameras – it would be great if this was an IP device I could simply view from my Android.  This inevitably led to searching for established hacks on the Levana, and as typically happens, determining that it would probably be cheaper to just purchase a regular IP camera for use on the network (which we will also probably do at some point in the future), searching the Android market for apps related to video monitoring, running across the IP Webcam app, and the recollection that we have a Samsung Acclaim laying around with a broken screen, just waiting to be given a purpose and to have new life breathed into it. After locating the phone, the first step was to “root” it.  This step is probably not essential for the basic webcam functionality and can be skipped if you don’t require the remote access, firewalling, or logging I plan to implement in subsequent steps.  For the Acclaim, I used the intercept-root application available at http://intercept-root.googlecode.com/files/interceptRoot.apk.  If you enable installation from unknown sources (Settings -> Applications -> Unknown sources), you can download directly to your phone using the browser and install in two clicks once the download is complete.  The exploit took after running twice, and I had a rooted device. Part of the reason I hadn’t yet repurposed this device was the presence of SMS/MMS messages that we wanted to save.  A little searching led me to SMS Backup + in the market, which turned out to be an amazingly slick little app that I set up to back up my own SMS, MMS, and call records as well.  I did encounter one error while running the backup on the Acclaim, but simply hitting the Stop button in the application caused it to clear and continue with the backup process. Once message backup was complete, I performed a factory reset on the phone to remove all unneeded applications and data.  The phone rebooted with factory default configuration, and I set it in airplane mode and configured my wireless network settings.  I reinstalled the root application (optional, and not absolutely necessary as the phone retains root through the reset).  Because I use two factor authentication with my Google account, I needed to set up a single-use password under my Google account just for this phone.  The Market application automatically updated to the Play Store, and I installed Titanium Backup to allow the removal of a few items I didn’t really need.  At this point I noticed that my e-mail and contacts had sync’ed to the phone, which I didn’t really want or need, so I went ahead and disabled automatic synchronization.  In hindsight I should have set up the account and disabled synchronization right away, but I’m not significantly concerned about it for the time being; I have considered removing the GMail application from the device, but I’m not yet sure if I will end up needing it for any type of alerting/notification from the camera. Since the phone was up on my wifi connection at this time, I also added a static DHCP reservation for it on my wireless router.  This procedure varies by router model, but is generally fairly well documented with a little searching.  I wanted to have an SSH server installed on the phone so I have a way to access it without having to physically hold it in my hand, as well as to provide an option for tunneling video from the camera across a secure connection.  This is also overkill in most environments, but is an option if you choose to do so.  I ended up using SSHDroid as an SSH server after initially wasting several hours trying to get DropBear to start.  Interestingly enough there were some additional benefits to SSHDroid that I wasn’t expecting (like bash command completion and automatic color directory listings), so it was definitely worthwhile.  Just wish I had done it sooner.

I’ve had this post sitting as a draft for a while, and I think in the interest of perhaps having it be helpful to someone I’ll go ahead and get it posted.  Not a lot of meat to it, mostly just notes my setup steps.  The IPCam application definitely does as it says, though I have to admit that I haven’t played around with the camera as much as I originally thought I might.  But I can definitely see setting it up on my normal phone and my wife’s, perhaps in conjunction with making an infrared LED flashlight, and using it to keep an eye on the girls in the camper if we want to sit outside while they are sleeping.

Be the first to comment

BerkeleyX edX courses

Posted January 12, 2013 By Landis V

https://www.edx.org/courses/BerkeleyX/Stat2.1x/2013_Spring/about – Introduction to Statistics:  Descriptive Statistics

https://www.edx.org/courses/BerkeleyX/CS191x/2013_Spring/about – Quantum Mechanics and Quantum Computation

Ran across these while looking at Scratch as something my kids might be interested in at some point.  I’ve always wanted to take a statistics course… this might be just the opportunity I have been looking for (if I can find the time 🙁 )

Be the first to comment

http://www.computerworld.com/slideshow/detail/79661/How-to-create-an-automatically-updating-Google-spreadsheet

Pretty handy trick.  I’ve done parts of it, but not the JSON parsing or the scheduling.  Those may be new since I last looked.  Good to hold on to for a reference.

Be the first to comment

Grocery price tracking

Posted January 6, 2013 By Landis V

For some time (at least two years now) I’ve been tracking grocery prices on a few items that I buy regularly.  I’ve handled this through a spreadsheet in Google Docs, but more and more I’ve been interested in getting this into a database.  In conjunction with some things I’ve been looking at for home inventory, I decided to give xataface a try in this category as well.  I’ve spent some time with it this weekend, and while I’m a long way from finished, I’ve at least got something that should be simple to enter data from across the board.  Additionally, I’m looking at acquiring a couple of barcode scanners next week to further the project 🙂  Here’s what most of my weekend outside of family activities has consisted of.

Install (Linux – already done,) Apache, MySQL, and PHP.

Create a database for the application

create database grocery_price;

Add database user and grant privileges

CREATE USER ‘gprice’@’localhost’ IDENTIFIED BY ‘secretpassword’;
GRANT INSERT, SELECT, DELETE, UPDATE ON grocery_price.* TO ‘gprice’@’localhost’;

Create the tables for storing grocery items and purchases.  Each grocery will need to have an ID; it would be ideal to have it be the UPC/EIN(?) code, but not all receipts have that (indeed, not even all products have it… think vegetables), and if items are not scanned as they come in it simply wouldn’t work.  Right now about 25% of my spreadsheet entries (103 out of 397) have blank SKU fields, others have store SKUs, and probably the majority have a UPC or partial UPC.  Initially creating a table that matches up to entry lines in existing database, maybe with a true/false marker for “SKU is UPC”.

CREATE TABLE grocery_price.entry (
entryID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
createtime DATETIME DEFAULT NULL,
updatetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
brand VARCHAR(55),
type VARCHAR(40) COMMENT ‘generic classification for product i.e. juice, cheese, wine’,
subtype VARCHAR(55) COMMENT ‘more descr clsfcation for product i.e. apple, colby, shiraz’,
description VARCHAR(255) COMMENT ‘freeform name of product with more description/keywords’,
count TINYINT UNSIGNED DEFAULT 1 COMMENT ‘count of item purchased; 0 if observed only’,
size FLOAT COMMENT ‘number of ounces, mL, units, count, etc’,
unit VARCHAR(20) COMMENT ‘ounces, mL, lbs, each, etc.’,
price DECIMAL(6,2) COMMENT ‘price per item unless next field – priceisperitem – is 0’,
priceisperitem BIT(1) DEFAULT 1 COMMENT ‘true/set unless the price in the row is for count’,
regularprice DECIMAL(6,2) NULL COMMENT ‘if onsale and regular price recorded’,
store VARCHAR(80),
rcptdesc VARCHAR(80) COMMENT ‘description of product as displayed on receipt’,
sku VARCHAR(40) COMMENT ‘SKU from receipt or preferably UPC w or w/o check digit’,
skuisupc BIT(1) DEFAULT 1 COMMENT ‘1/true if the SKU field is a UPC w or w/o a check digit’,
upc BIGINT,
pricedate DATE COMMENT ‘date on receipt if a purchase, otherwise date price seen’,
location VARCHAR(80),
note VARCHAR(255));
*  If the “skuisupc” field is set to 1, should have a stored procedure/function automatically update/insert the “upc” field when the record is first entered – and preferably calculate and add the check digit if it is not present.  UPC has 11 digits + check, EAN has 12+1 check, can convert UPC to EAN by adding a 0 at the beginning.  This is not finished yet, what is below is just a start on an outline for it.  Might just accept what it has if I have marked it as valid for the time being.
1.  Check length.  If 11 or less, assume UPC without check digit and left pad zeros to a length of 12, run EAN check calculation.
2.  If length is 12
DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_setupc`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW

BEGIN
IF NEW.skuisupc = 1 THEN SET NEW.upc = NEW.sku;
END IF;
END $$
DELIMITER ;
*  Also need to have a stored procedure/function/trigger automatically set the updatetime field on an ‘UPDATE’ action
DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_createtime`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW
BEGIN

SET NEW.createtime = CURRENT_TIMESTAMP();

END $$

DELIMITER ;

Load CSV data into the file.  CSV contains columns for brand, type, subtype, description, size, unit, price, regularprice, store, rcptdesc, sku, skuisupc, pricedate, location, notes.

LOAD DATA INFILE ‘/home/landisv/Documents/grocery.csv’ INTO TABLE `grocery_price`.`entry` FIELDS TERMINATED BY ‘,’ ENCLOSED BY ‘”‘ LINES TERMINATED BY ‘\n’ (brand, type, subtype, description, size, unit, price, regularprice, store, rcptdesc, sku, skuisupc, pricedate, location, note);

Permitted mysqld access through apparmor as per http://stackoverflow.com/questions/4215231/mysql-load-data-infile-error-code-13.

Installed php5-mysql

apt-get install php5-mysql

Attempted setup for initial application, which failed.

php makesite ../grocery gprice:w1WnmAV4P9QdTT93Gbhk@localhost/grocery_price /xataface

Granted gprice user proper permissions

SHOW GRANTS FOR `gprice`@`localhost`;
GRANT INSERT, SELECT, DELETE, UPDATE ON `grocery_price`.* TO `gprice`@`localhost`;

Reran creation command successfully.  Attempted to access the web application and received the following message:  “As of Xataface 1.3 all applications are now required to have its own templates_c directory to house its compiled templates. Please create the directory “/var/www/grocery/templates_c” and ensure that it is writable by the web server.”

Created the templates_c directory and changed its ownership to the webserver.
cd /var/www/grocery
mkdir templates_c
chown www-data:www-data templates_c/

Getting HTTP 500 errors.  Did a little reading, installed php-pear and smarty engine.

apt-get install php-pear smarty

Still returning errors.  Viewed apache logs, noted that the database user I was working with (which I had only granted insert, select, update, and delete privileges to) needed create permissions (on a couple of tables as I discovered working through the issue).  Granted create permissions to the gprice user as follows.

GRANT CREATE ON `grocery_price`.`dataface__version` TO `gprice`@`localhost`;
GRANT CREATE ON `grocery_price`.`dataface__mtimes` TO `gprice`@`localhost`;
GRANT CREATE ON `grocery_price`.`dataface__preferences` TO `gprice`@`localhost`;

Once the above permissions were granted, I was able to access the database from the web interface.  Pretty ugly right now, as there are a couple of fields there’s really no need to see from the user interface (timestamps specifically), but it does work.  Also just noted that my rcptdate/pricedate stamps are ugly as sin and broken, so will probably drop the ‘entry’ table and recreate it, fix the CSV in the format expected by MySQL, and re-import it.  Sure enough, checking CSV indicates date format is MM/DD/YY, and for the DATE datatype MySQL will be expecting it as YYYY-MM-DD.  Ended up being easier to fix the date format in Google Docs and redownload, so I did that.  Ran the following to drop and recreate the ‘entry’ database table.

DROP TABLE entry;
CREATE TABLE grocery_price.entry (
entryID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
createtime DATETIME DEFAULT NULL,
updatetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
brand VARCHAR(55),
type VARCHAR(40) COMMENT ‘generic classification for product i.e. juice, cheese, wine’,
subtype VARCHAR(55) COMMENT ‘more descr clsfcation for product i.e. apple, colby, shiraz’,
description VARCHAR(255) COMMENT ‘freeform name of product with more description/keywords’,
count TINYINT UNSIGNED DEFAULT 1 COMMENT ‘count of item purchased; 0 if observed only’,
size FLOAT COMMENT ‘number of ounces, mL, units, count, etc’,
unit VARCHAR(20) COMMENT ‘ounces, mL, lbs, each, etc.’,
price DECIMAL(6,2) COMMENT ‘price per item unless next field – priceisperitem – is 0’,
priceisperitem BIT(1) DEFAULT 1 COMMENT ‘true/set unless the price in the row is for count’,
regularprice DECIMAL(6,2) NULL COMMENT ‘if onsale and regular price recorded’,
store VARCHAR(80),
rcptdesc VARCHAR(80) COMMENT ‘description of product as displayed on receipt’,
sku VARCHAR(40) COMMENT ‘SKU from receipt or preferably UPC w or w/o check digit’,
skuisupc BIT(1) DEFAULT 1 COMMENT ‘1/true if the SKU field is a UPC w or w/o a check digit’,
upc BIGINT,
pricedate DATE COMMENT ‘date on receipt if a purchase, otherwise date price seen’,
location VARCHAR(80),
note VARCHAR(255));
DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_setupc`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW

BEGIN

IF NEW.skuisupc = 1 THEN SET NEW.upc = NEW.sku;

END IF;

END $$

DELIMITER ;
DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_createtime`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW

BEGIN

SET NEW.createtime = CURRENT_TIMESTAMP();

END $$

DELIMITER ;

Received a message at this point that current version of MySQL doesn’t support multiple triggers with the same action.  Makes sense, so I revamped those a little and combined them into one, dropped the table, and re-added as follows.

CREATE TABLE grocery_price.entry (
entryID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
createtime DATETIME DEFAULT NULL,
updatetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
brand VARCHAR(55),
type VARCHAR(40) COMMENT ‘generic classification for product i.e. juice, cheese, wine’,
subtype VARCHAR(55) COMMENT ‘more descr clsfcation for product i.e. apple, colby, shiraz’,
description VARCHAR(255) COMMENT ‘freeform name of product with more description/keywords’,
count TINYINT UNSIGNED DEFAULT 1 COMMENT ‘count of item purchased; 0 if observed only’,
size FLOAT COMMENT ‘number of ounces, mL, units, count, etc’,
unit VARCHAR(20) COMMENT ‘ounces, mL, lbs, each, etc.’,
price DECIMAL(6,2) COMMENT ‘price per item unless next field – priceisperitem – is 0’,
priceisperitem BIT(1) DEFAULT 1 COMMENT ‘true/set unless the price in the row is for count’,
regularprice DECIMAL(6,2) NULL COMMENT ‘if onsale and regular price recorded’,
store VARCHAR(80),
rcptdesc VARCHAR(80) COMMENT ‘description of product as displayed on receipt’,
sku VARCHAR(40) COMMENT ‘SKU from receipt or preferably UPC w or w/o check digit’,
skuisupc BIT(1) DEFAULT 1 COMMENT ‘1/true if the SKU field is a UPC w or w/o a check digit’,
upc BIGINT,
pricedate DATE COMMENT ‘date on receipt if a purchase, otherwise date price seen’,
location VARCHAR(80),
note VARCHAR(255));
DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_insert`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW
BEGIN

SET NEW.createtime = CURRENT_TIMESTAMP();

IF NEW.skuisupc = 1 THEN SET NEW.upc = NEW.sku;

END IF;

END $$
DELIMITER ;
LOAD DATA INFILE ‘/home/landisv/Documents/grocery.csv’ INTO TABLE `grocery_price`.`entry` FIELDS TERMINATED BY ‘,’ ENCLOSED BY ‘”‘ LINES TERMINATED BY ‘\n’ (brand, type, subtype, description, size, unit, price, regularprice, store, rcptdesc, sku, skuisupc, pricedate, location, note);

This worked great.  The downside is that the UPC import sucked, and I will probably drop those columns (upc and skuisupc) for the time being until I get around to adding them and the associated triggers as bitmaps.  For now I will just hide them.

Created a fields.ini folder (readable/writable by the webserver) in the /var/www/grocery/tables/entry directory with the following contents.
[entryID]
widget:type = “hidden”
[createtime]
widget:type = “hidden”
[updatetime]
widget:type = “hidden”
[skuisupc]
widget:type = “hidden”
[upc]
widget:type = “hidden”

This eliminated the fields in the detail edit view, but they still appear in the detail view itself as well as the list view.  Something else to probably work on over time.  At this point I tried adding a record by copying, which works fairly well (my test was primarily to check on the create/update time and ID fields to make sure they were unique with the copy).  Unfortunately I noticed that my prices all failed the import.  I suspect this is due to having a dollar sign in the CSV fields.  Since I’ll be redoing the table anyway, will go ahead and drop the ‘skuisupc’ and ‘upc’ fields out of it – and also see how xataface handles still having these fields in the fields.ini file 🙂  Ran the following.

CREATE TABLE grocery_price.entry (
entryID INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
createtime DATETIME DEFAULT NULL,
updatetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
brand VARCHAR(55),
type VARCHAR(40) COMMENT ‘generic classification for product i.e. juice, cheese, wine’,
subtype VARCHAR(55) COMMENT ‘more descr clsfcation for product i.e. apple, colby, shiraz’,
description VARCHAR(255) COMMENT ‘freeform name of product with more description/keywords’,
count TINYINT UNSIGNED DEFAULT 1 COMMENT ‘count of item purchased; 0 if observed only’,
size FLOAT COMMENT ‘number of ounces, mL, units, count, etc’,
unit VARCHAR(20) COMMENT ‘ounces, mL, lbs, each, etc.’,
price DECIMAL(6,2) COMMENT ‘price per item unless next field – priceisperitem – is 0’,
priceisperitem BIT(1) DEFAULT 1 COMMENT ‘true/set unless the price in the row is for count’,
regularprice DECIMAL(6,2) NULL COMMENT ‘if onsale and regular price recorded’,
store VARCHAR(80),
rcptdesc VARCHAR(80) COMMENT ‘description of product as displayed on receipt’,
sku VARCHAR(40) COMMENT ‘SKU from receipt or preferably UPC w or w/o check digit’,
pricedate DATE COMMENT ‘date on receipt if a purchase, otherwise date price seen’,
location VARCHAR(80),
note VARCHAR(255));

DELIMITER $$
CREATE TRIGGER `grocery_price`.`entry_insert`
BEFORE INSERT ON `grocery_price`.`entry`
FOR EACH ROW

BEGIN

SET NEW.createtime = CURRENT_TIMESTAMP();

END $$

DELIMITER ;

LOAD DATA INFILE ‘/home/landisv/Documents/grocery.csv’ INTO TABLE `grocery_price`.`entry` FIELDS TERMINATED BY ‘,’ ENCLOSED BY ‘”‘ LINES TERMINATED BY ‘\n’ (brand, type, subtype, description, size, unit, price, regularprice, store, rcptdesc, sku, pricedate, location, note);

Didn’t observe any fits from the fields.ini file for the now missing fields, and my price information appears to have imported as expected.  All 397 of my records appear to have imported properly.  I also ran a really quick and dirty SQL injection attack which did not appear successful, so that’s a good indication as well (though a long ways from my forte, so I may not have done it correctly).

Attempted to add a record again and received another HTTP 500, though the record does appear to have been added.  Checked apache logs again and noted another table that needed CREATE permissions for the database user, added as follows.

GRANT CREATE ON `grocery_price`.`dataface__record_mtimes` TO `gprice`@`localhost`;

My next attempt to add a record appeared to work without error.  There’s still some tuning and visual improvement, as well as perhaps some selection list tie-ins to be added, but I’m pleased with the results for now.

1 Comment. Join the Conversation