Igor Kromin |   Consultant. Coder. Blogger. Tinkerer. Gamer.

I run DietPi on my Raspberry Pi 2, which I use exclusively for programming Atari Lynx cartridges via the Lynx Cart Programmer Pi-Hat and as a result the Raspberry Pi is only ever turned on when I need to burn ROMs to cartridges. Usually this is a quick process but sometimes I noticed it runs into errors on boot with the "Waiting for Dietpi-Postboot to finish (x/15) - syntax error in expression" error appears over and over.

I've put up with this for a while but eventually it got the better of me and I had to fix it. Turned out the fix was really quite simple!
IMG_2952.jpg


Continue reading...  

, , ,

If you've been following my articles you would know that I've had an Odroid XU4 since 2016 and it's still going strong. Over that time I've gone through a number of enclosures with the final iteration being an open to air (deconstructed if you will) design. There are obvious disadvantages to that, dust being the biggest, so when an opportunity came up to check out the KKSB Odroid XU4Q Case With Fan I jumped at it.

KKSB Cases offers two variants of cases for the XU4, the aforementioned KKSB Odroid XU4Q Case With Fan as well as the more slimline KKSB Odroid XU4 Case. The former is able to support the tall/extended heatsink in either the standard blue or the flared gold style. The latter is designed to accommodate the standard heatsink with fan.
IMG_3015.jpg


I received both cases from KKSB and both were quite aesthetically pleasing. Each of the cases had two parts which are powder coated - the top part in black and bottom in an off-white colour. The top simply slides over the bottom section and has two notches on either side that protrusions in the bottom slide into. This is a very neat mechanism that required no screws to assemble. I did find the top part easy to bend when it was on its own, but once connected with the bottom it was quite solid. Both cases came with screws to secure your XU4 and the larger of the cases had a small fan included too. More on this later.

First lets check out these cases. Did I mentioned they looked amazing? I really liked the contrast between the top and bottom and the clean lines from laser cut metal construction were just so appealing.

IMG_3016.jpg IMG_3017.jpg

IMG_3018.jpg IMG_3019.jpg


Continue reading...  

, ,

One of the websites I help maintain uses an older version of PrestaShop (1.4.6.2) and since enabling SSL I've noticed that the BlockCMS module editor hasn't been behaving very well. Specifically, it wasn't showing any of the CMS pages that were created so it wasn't possible to select what links were shown on the shop's sidebar.

The BlockCMS editor had everything except for the section that let you pick which pages to display in the block...
blockcms_1.png


What I saw when I opened the developer console explained everything. The browser was blocking non-SSL content that the BlockCMS module was requesting. The blockcms.js JavaScript file was the one being blocked and that file is responsible for providing functions that populate the BlockCMS editor.
blockcms_2.png


After some digging around I found the problem. It was in the modules/blockcms/blockcms.php file.
blockcms_4.png


Continue reading...  

, , ,

Some of the work I've been doing not so long ago has been deeply rooted in PL/SQL which was invoked from a Java client. The PL/SQL made heavy use of DBMS_OUTPUT to generate text data that could be parsed by the Java client, which in turn then generated graphs (as images). I needed an easy way of capturing this output and unfortunately when I looked around all I could find were outdated approaches that didn't make use of Java features like AutoCloseable resources, and then there were some examples that plain didn't work.

So I decided to build my own...
 DbmsOutputCapture.java
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class DbmsOutputCapture implements AutoCloseable {
private static final int DEFAULT_LINE_BUF_SZ = 1024;
private int lineBufferSize;
private CallableStatement enableStmt;
private CallableStatement readLineStmt;
private CallableStatement disableStmt;
public DbmsOutputCapture(Connection dbConn)
throws SQLException
{
this(dbConn, DEFAULT_LINE_BUF_SZ);
}
public DbmsOutputCapture(Connection dbConn, int lineBufferSize)
throws SQLException
{
this.lineBufferSize = lineBufferSize;
enableStmt = dbConn.prepareCall("begin dbms_output.enable(NULL); end;");
disableStmt = dbConn.prepareCall("begin dbms_output.disable(); end;");
readLineStmt = dbConn.prepareCall("begin dbms_output.get_lines(?, ?); end;");
readLineStmt.registerOutParameter(1, Types.ARRAY,"DBMSOUTPUT_LINESARRAY");
readLineStmt.registerOutParameter(2, Types.INTEGER,"INTEGER");
readLineStmt.setInt(2, lineBufferSize);
}
public List<String> execute(CallableStatement userCall)
throws SQLException
{
List<String> retLines = new ArrayList<>();
try {
enableStmt.executeUpdate();
userCall.execute();
int fetchedLines;
do {
readLineStmt.execute();
fetchedLines = readLineStmt.getInt(2);
Array array = null;
try {
array = readLineStmt.getArray(1);
String[] lines = (String[]) array.getArray();
/* loop over number of returned lines, not array size */
for (int i = 0; i < fetchedLines; i++) {
String line = lines[i];
retLines.add(line != null ? line : "");
}
}
finally {
if (array != null) {
array.free();
}
}
} while(fetchedLines == lineBufferSize);
}
finally {
disableStmt.execute();
}
return retLines;
}
@Override
public void close()
throws SQLException
{
if (!quietClose(enableStmt, readLineStmt, disableStmt)) {
throw new SQLException("Could not close all callable statements");
}
}
private boolean quietClose(CallableStatement ... callableStatements) {
boolean allSuccess = true;
for (CallableStatement stmt : callableStatements) {
try {
stmt.close();
}
catch (SQLException e) {
allSuccess = false;
}
}
return allSuccess;
}
}


Continue reading...  

, , , ,