Sponsored

Decoding the AB file with VBA (and a bonus pointless math lesson)

RadioDoc

2.5L Hybrid
Well-known member
Joined
May 30, 2023
Threads
7
Messages
99
Reaction score
97
Location
Fairchild AFB, WA
Vehicle(s)
2023 Maverick XLT Hybrid Lux
Engine
2.5L Hybrid
So a little side project that I'm (slowly) working on is picking apart the AB file using my programming language of choice - VBA (yes, yes, people may mock it, but it's all I have available in my work environment where I normally use it).

Anyways, my end goal here will be to take the entirety of the Livnitup spreadsheets and whip up a tool that'll let me feed the AB file into it, reconfigure it as I want according to the various rules set, then build up a file I can push back into the truck via FORScan, or at the very least give me the per address code blocks required complete with the correct checksum in the last two positions. Or some quick adjustments like change all MPH references to KPH, 1-click setup of various mods (TSR/SSR, unlocking the MyView screens, etc.), or some fast QOL items like disabling speed lockouts on menus where we've figured out how to do so. Or maybe a compare tool so I can bump the AB vs a FORScan ABT if I can figure out how the ABT files are put together. Or even a way to "sanitize" an AB (i.e. stripping key parts out of the VIN that are encoded throughout the modules) for sharing. I'm mainly doing this as an exercise in learning how to manipulate XML files with VBA, but in case anyone else wanted to play with the AB file as well I figured I'd share what I have to start.

At this point, I'm just setting up a framework that will let me read the labels and the individual code blocks, eventually this will balloon into an Access based utility with a more user-friendly interface. Right now it'll just dump the contents of the AB file to the Immediate window, but that should be enough for anyone to get started on their own project.
Code:
Function ImportAB()
'Requires the following references:
'- Microsoft Office 16.0 Object Library
'- Microsoft XML, v6.0
Dim fdialog As Office.FileDialog
Dim selfile
Dim xDoc As MSXML2.DOMDocument60
Dim xnode As MSXML2.IXMLDOMNode
Dim PCMNode As MSXML2.IXMLDOMNode
Dim BCENode As MSXML2.IXMLDOMNode
Dim codeint As Integer
Dim codetxt As String
Set xDoc = New MSXML2.DOMDocument60
Set fdialog = Application.FileDialog(msoFileDialogFilePicker)
With fdialog
    .AllowMultiSelect = False
    .Title = "Select AS BUILT file to import"
    .Filters.Clear
    .Filters.Add "Ford OEM AS BUILT Data", "*.ab"
    .Filters.Add "All Files", "*.*"
    If .Show = True Then
        selfile = .SelectedItems(1)
    End If
End With
'codeint below is used as a counter for which of the 3 code blocks is currently being looked at
xDoc.async = False
If xDoc.Load(selfile) Then
    For Each PCMNode In xDoc.getElementsByTagName("PCM_MODULE")
        If PCMNode.ChildNodes.Length <> 0 Then
            For Each cnode In PCMNode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
    For Each BCENode In xDoc.getElementsByTagName("BCE_MODULE")
        If BCENode.ChildNodes.Length <> 0 Then
            For Each cnode In BCENode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
End If
Set xDoc = Nothing
End Function
BONUS POINTLESS MATH LESSON:
If anyone was curious how the checksums are calculated, drop the last 2 positions off the code blocks (i.e. if the code is 0000 0020 0018, drop the 18 at the end), then put together the input string as "0 & [address] & [code blocks]" (ex - 6F0-01-01: 0000 0020 0018 -> 06F001010000002000). Next, split into 5/7/9 bytes of 2 characters each (in this case, 9 bytes - 06 F0 01 01 00 00 00 20 00) then convert each byte from hexadecimal to decimal and sum up the result (6+240+1+1+0+0+0+32+0=280) and then find the modulo of that with 256 as the modulus (280 mod 256 = 24) or in layman's terms divide the sum by 256 and get the remainder. Convert that from decimal back to hexadecimal and there's your checksum (24 dec = 18 hex). Interesting? Maybe. Useful? Only if you're tweaking AB values and don't want FORScan yelling at you. Definitely recommend setting up a table in your spreadsheet software of choice to handle all the number crunching, because it is stupidly tedious by hand.
Sponsored

 

MetalsGeek

2.5L Hybrid
Well-known member
First Name
Rough
Joined
Jan 9, 2022
Threads
5
Messages
682
Reaction score
820
Location
Torrance, CA 90503
Vehicle(s)
Down to just the Mav
Engine
2.5L Hybrid
My fave will always be C++, but VBA is a very capable language. I wrote a VBA app that ran under Excel to optimize the metric change gears for my lathe, and it worked very well. Some years ago, the Joint Mission Planning System for military aircraft was developed mostly in VB, so it's quite a capable language. That being said, I would personally keep your app as simple as possible and avoid using Access since not everyone has that available. A journey of 1,000 miles begins with a single step...
 

TCPTX65

2.5L Hybrid
Well-known member
First Name
Tim
Joined
Dec 18, 2021
Threads
25
Messages
672
Reaction score
1,053
Location
Texas
Vehicle(s)
2023 Maverick XL Hybrid, 2023 Buick Enclave
Engine
2.5L Hybrid
Clubs
 
So a little side project that I'm (slowly) working on is picking apart the AB file using my programming language of choice - VBA (yes, yes, people may mock it, but it's all I have available in my work environment where I normally use it).

Anyways, my end goal here will be to take the entirety of the Livnitup spreadsheets and whip up a tool that'll let me feed the AB file into it, reconfigure it as I want according to the various rules set, then build up a file I can push back into the truck via FORScan, or at the very least give me the per address code blocks required complete with the correct checksum in the last two positions. Or some quick adjustments like change all MPH references to KPH, 1-click setup of various mods (TSR/SSR, unlocking the MyView screens, etc.), or some fast QOL items like disabling speed lockouts on menus where we've figured out how to do so. Or maybe a compare tool so I can bump the AB vs a FORScan ABT if I can figure out how the ABT files are put together. Or even a way to "sanitize" an AB (i.e. stripping key parts out of the VIN that are encoded throughout the modules) for sharing. I'm mainly doing this as an exercise in learning how to manipulate XML files with VBA, but in case anyone else wanted to play with the AB file as well I figured I'd share what I have to start.

At this point, I'm just setting up a framework that will let me read the labels and the individual code blocks, eventually this will balloon into an Access based utility with a more user-friendly interface. Right now it'll just dump the contents of the AB file to the Immediate window, but that should be enough for anyone to get started on their own project.
Code:
Function ImportAB()
'Requires the following references:
'- Microsoft Office 16.0 Object Library
'- Microsoft XML, v6.0
Dim fdialog As Office.FileDialog
Dim selfile
Dim xDoc As MSXML2.DOMDocument60
Dim xnode As MSXML2.IXMLDOMNode
Dim PCMNode As MSXML2.IXMLDOMNode
Dim BCENode As MSXML2.IXMLDOMNode
Dim codeint As Integer
Dim codetxt As String
Set xDoc = New MSXML2.DOMDocument60
Set fdialog = Application.FileDialog(msoFileDialogFilePicker)
With fdialog
    .AllowMultiSelect = False
    .Title = "Select AS BUILT file to import"
    .Filters.Clear
    .Filters.Add "Ford OEM AS BUILT Data", "*.ab"
    .Filters.Add "All Files", "*.*"
    If .Show = True Then
        selfile = .SelectedItems(1)
    End If
End With
'codeint below is used as a counter for which of the 3 code blocks is currently being looked at
xDoc.async = False
If xDoc.Load(selfile) Then
    For Each PCMNode In xDoc.getElementsByTagName("PCM_MODULE")
        If PCMNode.ChildNodes.Length <> 0 Then
            For Each cnode In PCMNode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
    For Each BCENode In xDoc.getElementsByTagName("BCE_MODULE")
        If BCENode.ChildNodes.Length <> 0 Then
            For Each cnode In BCENode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
End If
Set xDoc = Nothing
End Function
BONUS POINTLESS MATH LESSON:
If anyone was curious how the checksums are calculated, drop the last 2 positions off the code blocks (i.e. if the code is 0000 0020 0018, drop the 18 at the end), then put together the input string as "0 & [address] & [code blocks]" (ex - 6F0-01-01: 0000 0020 0018 -> 06F001010000002000). Next, split into 5/7/9 bytes of 2 characters each (in this case, 9 bytes - 06 F0 01 01 00 00 00 20 00) then convert each byte from hexadecimal to decimal and sum up the result (6+240+1+1+0+0+0+32+0=280) and then find the modulo of that with 256 as the modulus (280 mod 256 = 24) or in layman's terms divide the sum by 256 and get the remainder. Convert that from decimal back to hexadecimal and there's your checksum (24 dec = 18 hex). Interesting? Maybe. Useful? Only if you're tweaking AB values and don't want FORScan yelling at you. Definitely recommend setting up a table in your spreadsheet software of choice to handle all the number crunching, because it is stupidly tedious by hand.
Ford Maverick Decoding the AB file with VBA (and a bonus pointless math lesson) ogre-nerds
 

inline_five

2.5L Hybrid
Well-known member
Joined
Jun 15, 2023
Threads
32
Messages
1,159
Reaction score
1,611
Location
-
Vehicle(s)
2023 Hybrid XLT
Engine
2.5L Hybrid
So a little side project that I'm (slowly) working on is picking apart the AB file using my programming language of choice - VBA (yes, yes, people may mock it, but it's all I have available in my work environment where I normally use it).

Anyways, my end goal here will be to take the entirety of the Livnitup spreadsheets and whip up a tool that'll let me feed the AB file into it, reconfigure it as I want according to the various rules set, then build up a file I can push back into the truck via FORScan, or at the very least give me the per address code blocks required complete with the correct checksum in the last two positions. Or some quick adjustments like change all MPH references to KPH, 1-click setup of various mods (TSR/SSR, unlocking the MyView screens, etc.), or some fast QOL items like disabling speed lockouts on menus where we've figured out how to do so. Or maybe a compare tool so I can bump the AB vs a FORScan ABT if I can figure out how the ABT files are put together. Or even a way to "sanitize" an AB (i.e. stripping key parts out of the VIN that are encoded throughout the modules) for sharing. I'm mainly doing this as an exercise in learning how to manipulate XML files with VBA, but in case anyone else wanted to play with the AB file as well I figured I'd share what I have to start.

At this point, I'm just setting up a framework that will let me read the labels and the individual code blocks, eventually this will balloon into an Access based utility with a more user-friendly interface. Right now it'll just dump the contents of the AB file to the Immediate window, but that should be enough for anyone to get started on their own project.
Code:
Function ImportAB()
'Requires the following references:
'- Microsoft Office 16.0 Object Library
'- Microsoft XML, v6.0
Dim fdialog As Office.FileDialog
Dim selfile
Dim xDoc As MSXML2.DOMDocument60
Dim xnode As MSXML2.IXMLDOMNode
Dim PCMNode As MSXML2.IXMLDOMNode
Dim BCENode As MSXML2.IXMLDOMNode
Dim codeint As Integer
Dim codetxt As String
Set xDoc = New MSXML2.DOMDocument60
Set fdialog = Application.FileDialog(msoFileDialogFilePicker)
With fdialog
    .AllowMultiSelect = False
    .Title = "Select AS BUILT file to import"
    .Filters.Clear
    .Filters.Add "Ford OEM AS BUILT Data", "*.ab"
    .Filters.Add "All Files", "*.*"
    If .Show = True Then
        selfile = .SelectedItems(1)
    End If
End With
'codeint below is used as a counter for which of the 3 code blocks is currently being looked at
xDoc.async = False
If xDoc.Load(selfile) Then
    For Each PCMNode In xDoc.getElementsByTagName("PCM_MODULE")
        If PCMNode.ChildNodes.Length <> 0 Then
            For Each cnode In PCMNode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
    For Each BCENode In xDoc.getElementsByTagName("BCE_MODULE")
        If BCENode.ChildNodes.Length <> 0 Then
            For Each cnode In BCENode.ChildNodes
                codeint = 0
                codetxt = cnode.Attributes(0).NodeValue & ": "
                For Each xnode In cnode.ChildNodes
                    codeint = codeint + 1
                    codetxt = codetxt & xnode.Text & " "
                Next
                codetxt = Trim(codetxt)
                Debug.Print codetxt
            Next
        End If
    Next
End If
Set xDoc = Nothing
End Function
BONUS POINTLESS MATH LESSON:
If anyone was curious how the checksums are calculated, drop the last 2 positions off the code blocks (i.e. if the code is 0000 0020 0018, drop the 18 at the end), then put together the input string as "0 & [address] & [code blocks]" (ex - 6F0-01-01: 0000 0020 0018 -> 06F001010000002000). Next, split into 5/7/9 bytes of 2 characters each (in this case, 9 bytes - 06 F0 01 01 00 00 00 20 00) then convert each byte from hexadecimal to decimal and sum up the result (6+240+1+1+0+0+0+32+0=280) and then find the modulo of that with 256 as the modulus (280 mod 256 = 24) or in layman's terms divide the sum by 256 and get the remainder. Convert that from decimal back to hexadecimal and there's your checksum (24 dec = 18 hex). Interesting? Maybe. Useful? Only if you're tweaking AB values and don't want FORScan yelling at you. Definitely recommend setting up a table in your spreadsheet software of choice to handle all the number crunching, because it is stupidly tedious by hand.
I had a very similar thought to make a program that would do the same thing. I kinda put it on the back burner but props to you for continuing.

Python may be a more universal and easier accessible language to use.
 

Sponsored

OP
OP
RadioDoc

RadioDoc

2.5L Hybrid
Well-known member
Joined
May 30, 2023
Threads
7
Messages
99
Reaction score
97
Location
Fairchild AFB, WA
Vehicle(s)
2023 Maverick XLT Hybrid Lux
Engine
2.5L Hybrid
I had a very similar thought to make a program that would do the same thing. I kinda put it on the back burner but props to you for continuing.

Python may be a more universal and easier accessible language to use.
True, but at this time learning a new language on top of working though this project is a bit much. I'll get it going first in VBA, then look at porting later.
 
OP
OP
RadioDoc

RadioDoc

2.5L Hybrid
Well-known member
Joined
May 30, 2023
Threads
7
Messages
99
Reaction score
97
Location
Fairchild AFB, WA
Vehicle(s)
2023 Maverick XLT Hybrid Lux
Engine
2.5L Hybrid
Ok so I've got more of the code hammered out now, enough that I can dump the contents of the AB file's PCM and BCE sections into a table and whip up a form to let me pick through the data node by node. Still need to implement decoding rules for addresses where VINs or other info are encoded.

I'm seeing some weirdness in how FORScan is decoding and reading some fields (can't get to the FORScan website right now to explore this problem more), but for example the module configuration report says 7E4/BECM has a VIN attached to it, but when decoded the "VIN" isn't valid. However it does appear to have a part number or something similar embedded in addresses 7E4-01-04 through 7E4-01-06:

7E4-01-04354E5A36383Bxx**-****-**--5NZ68
7E4-01-052031304237EB****-****-**--10B7
7E4-01-06353920414506****-****-**--59AE

I pulled NZ68-10B759-AE out of that, and a quick Google search came back with eBay hits for " FORD PUMA Battery LX7A-10B759-AE 1.0 Hybrid 114KW 2023 48V 8Ah 350Wh " so looks like I just found a battery part number in the BECM. I'm guessing that the NZ68 is mainly used to denote the NA market, but the rest of the battery specs have me curious since the LX7A is showing up in Hybrid Pumas and Fiestas with the 1.0L EcoBoost.
Sponsored

 
 







Top