Tag Archive: C


We have built a reporting tool for the Clover ePos which creates a text report for printing using the built-in receipt printer. The app has been through numerous iterations and the code which specifically handles alignment has always bugged me. The task seems trivial to the human mind, but when trying to code seems to throw a lot of curve balls! Here are some examples of the anticipated behavior;

alignment_examples

So we revisited it, and I hope have now built a simpler “one size fits all” (not exactly, but considerably less conditional than before). The code accepts a string with pipe separators to determine alignment (refer to the diagram above for a bit more info) and spits out a string padded accordingly;

public static string Align(string key, int width)
        {
            string newKey = "";
            string[] keyElements = key.Split('|');

            if (keyElements.Length == 1)
            {
                newKey += key;
            }
            else if (keyElements.Length == 2)
            {
                //left align the first chunk
                newKey += keyElements[0];
                //insert blank spaces so the entire line length will be a multiple of width
                newKey += new string('.', width - ((key.Length - 1) % width));
                //insert the last chunk
                newKey += keyElements[1];
            }
            else if (keyElements.Length == 3)
            {
                if (keyElements[0] != "")
                {
                    //left align the first chunk 
                    newKey += keyElements[0];
                    //and pad the rest of the line
                    newKey += new string('.', width - (keyElements[0].Length % width));
                }
                //pad the left, center the second chunk and pad the right
                double sidePadding = width - (keyElements[1].Length % width);
                int leftPadding = (int)Math.Floor(sidePadding / 2);
                int rightPadding = (int)Math.Ceiling(sidePadding / 2);
                newKey += new string('.', leftPadding) + keyElements[1] + new string('.', rightPadding);

                if (keyElements[2] != "")
                {
                    //pad the line
                    newKey += new string('.', width - (keyElements[2].Length % width));
                    //and right align the last chunk
                    newKey += keyElements[2];
                }
            }

            return newKey;
        }

The receipt printer automatically wraps the string but we use a small method to split the string into chunks and add carriage returns/new lines for ease of use. Initially, this too was cumbersome (with loops and ifs etc), but we found a more elegant solution (avoiding re-inventing the wheel and reducing the number of lines of code- though I appreciate a loop is still occurring under the hood);

        public static string Wrap(string key, int width)
        {
            return Regex.Replace(key, ".{" + width + "}", "$0" + Environment.NewLine);
        }

 

Here’s some code we used to test the method(s);

        static void Main(string[] args)
        {
            int width = 33;

            List keys = new List();
            keys.Add("Simple");
            keys.Add("The|quick");
            keys.Add("This first part is really long|quick");
            keys.Add("The|second part is ridiculously long");
            keys.Add("The|quick|brown");
            keys.Add("The centre segment will always sit on it's own line|quick|brown");

            foreach (string key in keys)
            {
                Console.WriteLine(new string('=', width));
                Console.WriteLine("Input: " + key);
                Console.WriteLine(new string('-', width));
                string aligned = Align(key, width);
                string wrapped = Wrap(aligned, width);
                Console.WriteLine(wrapped);
            }

            Console.ReadKey();
        }

Can you think of any further way we can simplify/improve the code?

Further to a post over 3 years ago https://tickett.wordpress.com/2011/09/27/updateable-excel-frontend-for-sql-view/ – I have finally given up the search for a ready made solution and built something myself.

I work with a number of systems which have functionality gaps and/or need a simpler (quicker) interface for data entry. The solution is essentially a SQL view (or stored procedure) with a simple grid (excel like) front-end. If any data needs to be captured not currently handled by the system a custom table is created to hold the fields.

My previous Excel based solution works rather well, but is starting to show it’s age. I am now beta testing a web based solution i have built;

Screen Shot 2014-12-11 at 20.34.43

The application is extremely simple to configure- enter the SQL to retrieve & update the data;

Screen Shot 2014-12-11 at 20.43.43

And list the columns with some attributes (ReadOnly, Hidden, Title, Width etc);

Screen Shot 2014-12-11 at 20.42.10

And you’re all set!

Functionality currently includes;

  • Easy configuration
  • Simple/fast data entry (with validation)
  • Column resizing (non-persistent)
  • Sort on any column

Next steps;

  • Test (find and fix bugs)
  • Optimise code
  • Allow parameters in select SQL

The first project I backed on Kickstarter was delivered some time back but I’ve only recently gotten around to trying to do something with it.

I have a bunch of JeeNodes from JeeLabs and wanted to use them as a starting point so read a few articles about getting the RFM12B on the EVE talking to the Raspberry Pi. They suggest bridging CE1 to SS RFM12 and bridging G21/G27 to the third pin of the chip which appears to be FSK/DATA/nFFS (according to the data sheets I’ve seen)- oh and don’t forget to add an antenna!

I then found some code suggested to be working on the older v1 raspi with an RFM01 chip fitted rather than the RFM12B I have: http://www.susa.net/wordpress/2012/08/raspberry-pi-reading-wh1081-weather-sensors-using-an-rfm01-and-rfm12b/

Another site gave some pointers around modifying the code for the v2 raspi: http://amcc.me.uk/2013/01/eve-alpha-collects-weather-data/

The setup seems to work very well with either revision (1 or 2) of the Raspberry Pi though a couple of additional lines of code in wh1080_rf.c need to be tweaked to suit revision 2:

// RPi (Rev1) Init GPIO21 (on pin 13) as input (DATA), GPIO22 (pin 15) as output (nRES)
*(gpio.addr + 2) = (*(gpio.addr + 2) & 0xfffffe07)|(0x001 << 6);
Becomes:
// RPi (Rev2) Init GPIO27 (on pin 13) as input (DATA)
*(gpio.addr + 2) = (*(gpio.addr + 2) & 0xff1fffff)|(0x001 << 6)
And:
// RPi (Rev1) - GPIO21
status = ((*(gpio.addr + 13)) >> 21) & 1;
Becomes:
// RPi (Rev2) GPIO27
status = ((*(gpio.addr + 13)) >> 27) & 1;

I then went on to comment the RFM01 definition in rfm01.h and uncomment the RFM12B definition:

//#define RFM01
#define RFM12B

I also added the following definitions for the RFM12B as without them the code wouldn’t compile:

#define LNA_20 (3 << 4)
#define LNA_14 (1 << 4)
#define LNA_6 (2 << 4)
#define LNA_0 (0 << 4)
#define LNA_XX (3 << 4)

Remove this line from wh1080_rf.h:

#define USE_BMP085

Then onto the main wh1080_rf.c starting with updating to the correct spi port:

static const char *device = "/dev/spidev0.1";

I then used http://tools.jeelabs.org/rfm12b to get all the hex values to update the following lines:

uint16_t cmd_drate = 0xC606;
uint16_t cmd_freq = 0xA640;
uint16_t cmd_config= 0x80e7;
uint16_t cmd_power= 0x82dd;
uint16_t cmd_sync= 0xced4;
uint16_t cmd_afc= 0xc483;
uint16_t cmd_dcycle = 0xc800;
uint16_t cmd_pll= 0xcc57;
uint16_t cmd_fifo= 0xca83;
uint16_t cmd_dfilter = 0xc2ac;

Now when I:

make clean
make
sudo ./wh1080_rf

Initialising RFM12b
SPI: mode 0, 8-bit, 1000 KHz
Ctrl+C to exit
LNA_0,RSSI_73 idx 0 0.00 0.00 0.00 0.00 0.00 0.00
LNA_0,RSSI_79 idx 1 0.00 0.00 0.00 0.00 0.00 0.00
LNA_0,RSSI_85 idx 2 0.00 0.00 0.00 0.00 0.00 0.00
LNA_0,RSSI_91 idx 3 0.00 0.00 0.00 0.00 0.00 0.00
LNA_0,RSSI_97 idx 4 0.00 0.00 0.00 0.00 0.00 0.00
LNA_0,RSSI_103 idx 5 4.21 5.32 4.17 3.26 4.21 5.26
LNA_6,RSSI_73 idx 6 0.00 0.00 0.00 0.00 0.00 0.00
LNA_6,RSSI_79 idx 7 0.00 0.00 0.00 0.00 0.00 0.00
LNA_6,RSSI_85 idx 8 0.00 0.00 0.00 0.00 0.00 0.00
LNA_6,RSSI_91 idx 9 0.00 0.00 0.00 0.00 0.00 0.00
LNA_6,RSSI_97 idx 10 0.00 0.00 0.00 0.00 0.00 0.00
LNA_6,RSSI_103 idx 11 4.21 6.32 5.21 4.26 5.38 4.26
LNA_14,RSSI_73 idx 12 0.00 0.00 0.00 0.00 0.00 0.00
LNA_14,RSSI_79 idx 13 0.00 0.00 0.00 0.00 0.00 0.00
LNA_14,RSSI_85 idx 14 0.00 0.00 0.00 0.00 0.00 0.00
LNA_14,RSSI_91 idx 15 0.00 0.00 0.00 0.00 0.00 0.00
LNA_14,RSSI_97 idx 16 0.00 0.00 0.00 0.00 0.00 0.00
LNA_14,RSSI_103 idx 17 5.26 5.26 4.21 5.21 5.26 4.35
LNA_20,RSSI_73 idx 18 0.00 0.00 0.00 0.00 0.00 0.00
LNA_20,RSSI_79 idx 19 0.00 0.00 0.00 0.00 0.00 0.00
LNA_20,RSSI_85 idx 20 0.00 0.00 0.00 0.00 0.00 0.00
LNA_20,RSSI_91 idx 21 0.00 0.00 0.00 0.00 0.00 0.00
LNA_20,RSSI_97 idx 22 0.00 0.00 0.00 0.00 0.00 0.00
LNA_20,RSSI_103 idx 23 4.30 5.26 4.21 5.26 5.26 4.35
RSSI Duty 0.32

.

So the “interference” I can see suggests that something is hopefully working! I’m still playing around in an attempt to work out what I still need to tweak.

L

Crystal Report Data Source Updater

To address a long standing bug/issue with the Crystal Reports application forcing you to update every table/view/sproc one by one I built a quick/dirty application in c#.

You will need .NET installed and the Crystal runtime v13 to run it: http://snk.to/f-cztp0jk7

Here’s the code… no error trapping etc… I may improve it in the future:

            InitializeComponent();
            ReportDocument rpt = new ReportDocument();
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Crystal Reports (*.rpt)|*.rpt";
            ofd.ShowDialog();
            rpt.Load(ofd.FileName);
            ConnectionInfo ci = new ConnectionInfo();
            ci.ServerName = Microsoft.VisualBasic.Interaction.InputBox("Server");
            ci.DatabaseName = Microsoft.VisualBasic.Interaction.InputBox("Database");
            ci.UserID = Microsoft.VisualBasic.Interaction.InputBox("User");
            ci.Password = Microsoft.VisualBasic.Interaction.InputBox("Password");
            ci.IntegratedSecurity = (Microsoft.VisualBasic.Interaction.InputBox("SSPI (Y/N)") == "Y");
            TableLogOnInfo tli = new TableLogOnInfo();
            tli.ConnectionInfo = ci;
            for (int i = 0; i < rpt.Database.Tables.Count; i++)
            {
                rpt.Database.Tables[i].ApplyLogOnInfo(tli);
            }
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.DefaultExt = ".rpt";
            sfd.ShowDialog();
            rpt.SaveAs(sfd.FileName);
            Environment.Exit(0);

A few small updates

A few small updates as I have a ton of projects on the go at the moment.

FreeNas 8

After a friend visited earlier in the week I decided to give FreeNas / ZFS another shot- so I’ve installed the latest v8 on a spare HP Microserver N36L. The little cube has 4x 1.5TB Samsung disks in RAID-Z with a single 4GB stick of RAM. I have ordered another stick of RAM and a low profile, dual-port, gigabit pci-e network interface card (nic)- the HP NC360T (intel chipset) so I can setup load-balancing/link aggregation/LACP. I starting copying some data off of the current production Microserver (WHS2011):

Performance seems average. I’d expect to see a bit of an improvement when the gigabit HP / Intel nics arrive.

New Orders :)

I have put my Cisco SGE2000P 24-Port Gigabit managed PoE switch up on eBay as it’s a bit too big and loud for the small data/comms cabinet I bought recently. As a replacement I have ordered the D-Link DGS-1224TP which appears to offer the same feature set at half the size and half the weight (I think it may also be passively cooled and is touted as being "green" so hopefully help with the leccy bill :)

I also have a few Sonos S5 network wireless hifis on order (they were on special offer and I’ve been looking at whole house / multi-room audio distribution solutions for a while). I have a slight concern I may need to buy some Apple AirPort Express access points to enable AirPlay on them but I’ll cross that bridge as/when…

Apple Programming

I’m learning xcode / cocoa / objective-c / osx / iOS whatever they call it as I want to write a little app to control my 4×4 HDMI matrix. The device is on the network and supports simple commands using a telnet style socket connection, so I’m hoping it won’t be too tricky! Unfortunately I couldn’t find the old control software I had or documentation but eventually stumbled upon the pdf with a few pointers. So the reading begins… http://developer.apple.com/library/mac/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/_index.html#//apple_ref/doc/uid/TP40007594

L

%d bloggers like this: