Thursday, October 30, 2014

DevExtreme - Get dxTextBox value the JQuery way

Fairly simple. Let's say you have this:
<div id="batch-id"></div>
Which is converted to a dxTextBox:
$('#batch-id').dxTextBox();
And you want to get the value the official way:
var x = $('#batch-id').dxTextBox('instance').option('value');
You can set the value this way:
$('#batch-id').dxTextBox('instance').option('value', 666);
You can also directly query the element using classic jQuery:
$('#batch-id input').val();

Saturday, October 25, 2014

CoCo 2 with a PC 3.5 floppy drive

Now for something a little bit more vintage. I've revived my TRS-80 Color Computer 2 and wanted to give it an ultimate go with all the stuff that's now available on the net. The CoCo community is not very large, but it's still there. So I went on and tried to get the poor old thing to communicate with the now popular DriveWire 4 through a serial cable. But that's another blog post.

I'll talk here about the 3.5 inch floppy drive. They're still kind of available and cheap so, they're good replacements for the original 5.25 drives, and more reliable too. I looked around for many hours and found much complicated stuff, but I just wanted to sink a couple of boats in Battle Stations. So I decided to write this post, should it be helpful to someone one day, who also decides to blow some dust off their CoCo 2 ;)

Hooking the drive to a CoCo

Alright so here's what you'll need, no modification, no hack, no fiddling with the circuits:
  • A CoCo 2 system with a floppy disk controller.
  • A floppy cable, straight trough, with the two kinds of connectors (one "edge connector" for the controller, and a "plug connector" for the drive) Those used to be common. You could also use a edge to plug converter and use a more nowadays-common "all-plugs" cable.
  • A 3.5 floppy drive
  • A power source to power the drive.
This part is fairly easy. You just hook the drive to the controller. And that's it. I used the two connectors that were the closest to each other. Forgive the arrangement, it's messy, but it works:

I first used a nearby PC (they're everywhere in my appartment!) to power the drive.
Start the CoCo, type in DRIVE 1, and you're all set. You can insert a floppy, DSKINI1 on it, LOAD" from and SAVE" to it. You might have to put a piece of tape on the HD hole of the floppy to make it low density.

What if I need to use Drive 0?

For technical reasons, all standard PC floppy drives are hard wired to be DRIVE 1. Some have jumpers that make this configurable:
See DS1 and DS0? DS1 is jumped. You would have to unjump DS1 and jump DS0.
But that's not all. The CoCo uses a different technique than on PC to select which drive it talks to so the ordinary twisted cable won't work:
"There are 34 wires in the ribbon cable (1-34). Each odd wire is Ground. Each even wire is a control or data line. The Drive Select 0 and Drive Select 1 wires (numbers 12 and 14) are separated by 1 ground wire (13). 
You have to carefully remove the ribbon cable from the connector, seperate those three wires (DS0, GND, DS1) from the others and twist them so that the two drive select wires switch positions, then put all 34 wires back into the connector." -- Source

Writing a CoCo DSK image to a floppy from a PC

Here's what you'll need:
  • A PC (The OS will define which software you'll use. I used Debian.)
  • Another floppy drive attached to the motherboard of the PC. USB drives can't work.
I'll only talk about how to do it using Debian. Other Linux distros should have no real problem adapting the instructons. As for Windows, you're on your own, sorry... You might just want to get yourself a nice LiveBoot distribution of Ubuntu. Go ahead, the Linux turn nowadays is a fun and friendly journey! ;)

Ensure you have your floppy drive hooked to your motherboard. Then, you'll need fdutils so in a terminal:
sudo apt-get install fdutils
As a side note, no additional configuration of the utils is needed. apt will also install mtools as a dependency which will come with the proper /etc/mediaprm file configured with the correct CoCo entries in it.

Next:
  • Put a piece of tape on the HD hole of the floppy to make it low density ;)
  • Run the following command to tell the system how to format the disk. You'll have to run this every time you put a floppy in the drive:
sudo setfdprm /dev/fd0 coco1
  • Format the disk:
sudo fdformat /dev/fd0
  • Write the image to the disk:
sudo dd if=bstations.dsk of=/dev/fd0 
  • If any of the above two commands fail to read data from the disk, you might try to reenter the fdformat command and try again. this happened to me a couple of times.
  • Put the disk in the CoCo drive and sink some boats ;)

Reading a CoCo floppy to a DSK image on a PC

Install fdutils as explained above. Next, issue the setfdprm command explained above and enter:
sudo dd if=/dev/fd0 of=myimage.dsk count=315
If the dd command fails to write to the disk, you might have to enter the setfdprm command a couple of times before the dd command works, at least each time a floppy is inserted.

Floppy power source

If you want to build a power source yourself, you only need to provide 5V. Most floppies will need around 1A. No need for 12V. Be aware that the cartridge port of the CoCo has a 5V pin, but it is rated for 300mA only, so be safe and use an external source.
I used a spare D-Link wall adapter and replaced its connector with a floppy power connector I had left.

Hook both a 3.5 floppy drive and a CoCo drive to the CoCo

This is fairly easy. You'll need to ensure your floppy cable has enough connectors, and that there is no twist in between the used connectors.

Next, proceede to a "dental extraction" on the connector that'll connect the CoCo drive. Look at your original CoCo drive cable, if you have one, and look at the DRIVE 0 connector. You'll notice some pins (3) are missing. You'll have to remove them from your connector as well. So gently (those things are fragile like crystal) open the connector, remove the cable, remove the uneeded pins, put the cable back and reassemble the connector. Here's mine:
Notice the three removed pins. This is for DRIVE 0.
This is the whole setup.
There you have it. You can now backup your old 5.25 floppies to more trustworthy 3.5's!
You'll need one 3.5 for each 5.25 side, but who cares ;)

What if my 3.5 drive is DRIVE 0?

Then you want the CoCo as DRIVE 1. The process is the same, but the removed pins will be different:
This is for DRIVE 1 on the original CoCo cable. As a side note, also notice the straighten twist on the modified cable.

Additional infos

Here's a great repository of disk images I use myself. You'll find Battle Stations somewhere in there ;)

So this is what has worked for me. I tried a lot of things and failed many times, wondering each time what was wrong. Don't give up! I'd like to thank the guys at #coco_talk on freenode, they've been a great help and very friendly!

Feel free to ask any question in the comments below!

Wednesday, September 24, 2014

VS: Automatically create a NuGet Package from project upon build

Here's a neat little approach I use to effortlessly build NuGet packages.

- Get NuGet.exe and put it in the project folder. I also add it to our source control.
- Create a new Build Target named "NuGet". (optional, see below)
- In the Post Build Events of the project you want to make a NuGet package from, enter this:
if $(ConfigurationName) == NuGet (
  "$(ProjectDir)nuget.exe" pack "$(ProjectDir)$(ProjectFileName)" -OutputDirectory "\\target\directory\NuGet Feed" -Prop Configuration=$(ConfigurationName)
)
To use it, you just select the NuGet target, and build the project. It'll build the package and put it in the OutputDirectory folder.

The new "NuGet" target is in fact optional and you could use "Release" in the Post Build Event condition.

Also, you might want to edit the project's Assembly Infos and set the Company, Name, and Description properties. Pay special attention to the Version property too. Those properties appear in the NuGet package manager.

For more information on NuGet and how to get it, check this out.
To learn how to make a NuGet feed, check this out. Especially the local one. It's as simple as making a new directory, and this is what I use.

Have fun!

UPDATE:
Here's a NuGet with more features to do just that:
https://www.nuget.org/packages/CreateNewNuGetPackageFromProjectAfterEachBuild/

Friday, August 22, 2014

Entity Framework 6 Code First: error 3023: Problem in mapping fragments starting at lines xxxx:Column has no default value and is not nullable. A column value is required to store entity data

There are many reasons why this error would happen. There's a known bug in 6.1 which will be fixed in 6.2. But my problem wasn't related to it. Here's what happened for me.

I use a single table, tbl_Person,  to map a hierarchy, like this example, where Person is abstract :

And I use this mapping using Fluent API:

modelBuilder.Entity<Person>()
 .ToTable("tbl_Person")
 .HasKey(m => m.PersonID)
 .Map<Student =>(m.Requires (discrimination stuff) )
 .Map<Instructor>(m => m.Requires (discrimination stuff) )

And then later, I added another kind of Person to my model. Let's say a "Director"  but I forgot to add the mapping. That got me the error whenever I would try to use a DbContext. So I just added the mapping for "Director" and the error went away.

By the way, a discriminator column can be NOT NULL and have no default value, as opposed to what the error lead me to think.

Coffee time!

Tuesday, August 19, 2014

Entity Framework Code First: map to updatable view with INSTEAD OF INSERT trigger

At first, I was glad we could map entities to SQL views. Just map them to a view instead of a table. But when we need to update or delete, we need an updatable view. This is doable as explained here. My view was a join of multiple tables so I had to rely on an INSTEAD OF triggers. This works fine in theory or if you do your own queries. However, Entity Framework (v6 in my case) doesn't like them very much and I get this error when I add a new entity:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Here' why it thinks no rows were affected. Using SQL Server Profiler, I've been able to catch the following query that EF generates when I call SaveChanges() on my DbContext:

exec sp_executesql 
N'INSERT [dbo].[vw_ErpAndType]([Description], [ConnectionString], ...)
VALUES (@0, NULL, ...)
SELECT [idERP]
FROM [dbo].[vw_ErpAndType]
WHERE @@ROWCOUNT > 0 AND [idERP] = scope_identity()'
,N'@0 nvarchar(max) ,@1 bit, ...'
,@0=N'bill',@1=0 ...

See that part in bold and underlined red? This is how EF gets the key of the newly inserted row and give it back to the business object. The problem is that when there's an INSTEAD OF INSERT trigger, that scope_identity() instruction returns NULL because the trigger happens in another scope. So even if the insertion is successful, the query returns nothing and thus, EF thinks nothing happened and throws the error.

The workaround would be for EF to use @@identity instead but I don't believe we can do that.

This is as far as I went trying to use updatable views with EF. Now I'll see what can be done with mapped stored procedures for insert-delete-update.

Tuesday, July 1, 2014

Zebra EPL - Truncate text field

Zebra ZPL has this neat TB command which limits the field bounds. EPL doesn't seem to have this kind of feature. Here's how I've been able to do this. Place all the text fields in a form and use a variable with a maximum length:
V00,35,L,"" 
A600,30,1,4,6,2,N,V00 
A310,850,1,c,2,2,N,"ACCEPTED" 
?
1234567890123456789012345678901234567890
The result is:
1234567890123456789012345
ACCEPTED


Tuesday, May 20, 2014

DevExpress GridView CustomUnboundColumnData, e.Column always refers to same column

This just happened to me and the solution is very easy. I just didn't check for a solution at the right place. This will happen if your unbound columns all share the same FieldName, so make sure they are unique across the GridView.